ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

luogu P5406 [THUPC2019]找树

2022-02-22 20:01:39  阅读:173  来源: 互联网

标签:return int luogu ll len P5406 ret 找树 mod


https://www.luogu.com.cn/problem/P5406

首先要意识到这题不是最优化问题,而是计数类问题(光这点就不简单了)

考虑矩阵树定理计算的是什么

\[\sum_{T}\prod w_{e\in T} \]

这里\(\prod\)不一定是乘法,题目给出的这几个运算爷可以

于是乎可以构造集合幂级数\(x^{w}\),注意到\(FWT\)是线性运算,可以叠加,先\(FWT\)完,求个行列式,然后再\(IDFT\)回去即可

code:

#include<bits/stdc++.h>
#define ll long long
#define mod 998244353
using namespace std;
const int N = (1 << 12) + 5;
const int inv2 = (mod + 1) / 2;
char st[15];
void fwt(ll *a, int n, int o) {
    for(int len = 2, pos = 1; len <= n; len <<= 1, pos ++) {
        if(st[pos] == '|') {
            for(int j = 0; j < n; j += len)
                for(int k = j; k < j + (len >> 1); k ++)
                    a[k + (len >> 1)] = (a[k + (len >> 1)] + o * a[k] + mod) % mod;
        }
        if(st[pos] == '&') {
            for(int j = 0; j < n; j += len)
                for(int k = j; k < j + (len >> 1); k ++)
                    a[k] = (a[k] + o * a[k + (len >> 1)] + mod) % mod;
        }
        if(st[pos] == '^') {
            for(int j = 0; j < n; j += len)
                for(int k = j; k < j + (len >> 1); k ++) {
                    int X = a[k], Y = a[k + (len >> 1)];
                    a[k] = (X + Y) % mod, a[k + (len >> 1)] = (X - Y + mod) % mod;
                    if(o == -1) a[k] = a[k] * inv2 % mod, a[k + (len >> 1)] = a[k + (len >> 1)] * inv2 % mod;
                }
        }
    }
}
ll qpow(ll x, ll y) {
    ll ret = 1;
    for(; y; y >>= 1, x = x * x % mod) if(y & 1) ret = ret * x % mod;
    return ret;
}
ll a[75][75];
ll DET(int n) {
    ll ans = 1;
    for(int i = 1; i <= n; i ++) {
        int j = i;
        for(int k = i + 1; k <= n; k ++) if(a[k][i]) j = k;
        if(j != i) {
            ans = (mod - ans);
            swap(a[i], a[j]);
        }
        if(!a[i][i]) return 0;
        for(int j = i + 1; j <= n; j ++) {
            ll t = a[j][i] * qpow(a[i][i], mod - 2) % mod;
            for(int k = i; k <= n; k ++) {
                a[j][k] = (a[j][k] - t * a[i][k] % mod + mod) % mod;
            }
        }
    }
    for(int i = 1; i <= n; i ++) ans = ans * a[i][i] % mod;
    return ans;
}
int n, m, w, lim;
ll in[75][75][N], ans[N];
int main() {
    scanf("%d%d", &n, &m);
    scanf("%s", st + 1);
    w = strlen(st + 1);
    lim = (1 << w);
    for(int i = 1; i <= m; i ++) {
        int u, v, c;
        scanf("%d%d%d", &u, &v, &c);
        in[u][v][c] --, in[v][u][c] --;
        in[u][u][c] ++, in[v][v][c] ++;
    }
    for(int i = 1; i <= n; i ++)
        for(int j = 1; j <= n; j ++)
            for(int k = 0; k < lim; k ++)
                in[i][j][k] = (in[i][j][k] + mod) % mod;
    

    for(int i = 1; i <= n; i ++)
        for(int j = 1; j <= n; j ++) 
            fwt(in[i][j], lim, 1);
    
    for(int c = 0; c < lim; c ++) {
        for(int i = 1; i <= n; i ++)
            for(int j = 1; j <= n; j ++)
                a[i][j] = in[i][j][c];
        ans[c] = DET(n - 1);
    }
    fwt(ans, lim, -1);
    for(int i = lim - 1; i >= 0; i --) {
        if(ans[i]) {printf("%d", i); return 0;}
    }
    printf("-1");
    return 0;
}

标签:return,int,luogu,ll,len,P5406,ret,找树,mod
来源: https://www.cnblogs.com/lahlah/p/15924686.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有