loj548 「LibreOJ β Round #7」某少女附中的體育課

這道題好神啊!!!ios

發現這題就是定義了一種新的卷積,而後作k+1次卷積。ide

這裏咱們就考慮構造一個變換T,使得$T(a) \cdot T(b) =T(a∘b)$,這裏是讓向量右乘這個轉移矩陣。spa

因而咱們能夠獲得code

$$\sum_{j=0}^{m-1}{T_{j,i}  \sum{[k ∘ l =j] a_{k} b_{l}}  }   = (\sum_{j=0}^{m-1}{T_{j,i}a_{j}}) \cdot  (\sum_{j=0}^{m-1}{T_{j,i}b_{j}})$$blog

$$\sum{T_{k∘l,i}{a_{k}b_{l}}}= \sum{T_{k,i}T_{l,i}a_{k} b_{l}}$$get

設x爲T的某一列向量,這個變換知足的條件就是$x_{j}x_{k}=x_{j∘k}$string

又由於循環律,設$c_{i}$爲$i$的週期長度,咱們發現$x_{i^{c_{i}}}=x_{i}^{c_{i}}=x_{i}$,因此$x_{i}=w_{c_{i}}^{k} or 0$。it

以後咱們發現合法的狀況只有n種,考慮暴搜變換而後加上上面那個減枝就能夠了。io

而後咱們就獲得了咱們要求的變換,而後就像fwt同樣每一維依次進行變換就能夠了。class

正解依舊沒有看懂,個人理解就是按照$x^{0}$分紅若干個等價類,對於每一個等價類內dft構造出一個其中若干個變換,而後在將每一個小變換擴展所有,可是具體的怎麼dft以及如何擴展的我還不是特別明白,因此先挖個大坑吧。其實我以爲這種須要構造變換的題暴搜都是能夠碾壓正解的,由於暴搜加減枝的複雜度真的很優秀。

最後,LCA太神啦!

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <iostream>
 4 #include <algorithm>
 5 #include <cmath>
 6 #define mod 232792561
 7 #define N 500500
 8 #define M 25
 9 using namespace std;  10 int rt=71,n,m,all,f[N],tmp[N];  11 int A[M][M],a[M],cnt[M],tot,w[M][M],C[M][M],D[M][M];  12 long long K;  13 int qp(int a,int b){  14     int c=1;  15     for(;b;b>>=1,a=1ll*a*a%mod)  16         if(b&1)c=1ll*c*a%mod;  17     return c;  18 }  19 void UPD(int &a,int b){  20     a=(a+b>=mod)?(a+b-mod):(a+b);  21 }  22 bool can(int x){  23     for(int i=0;i<=x;i++)  24         for(int j=0;j<=x;j++)  25             if(A[i][j]<=x&&1ll*a[i]*a[j]%mod!=a[A[i][j]])return 0;  26     return 1;  27 }  28 void dfs(int x){  29     if(tot==m)return ;  30     if(x==m){  31         bool flag=0;  32         for(int i=0;i<m;i++)if(a[i])  33             {flag=1;break;}  34         if(!flag)return ;  35         for(int i=0;i<m;i++)C[i][tot]=a[i];  36         tot++;  37         return ;  38  }  39     for(int i=0;i<=cnt[x];i++){  40         a[x]=w[cnt[x]][i];  41         if(can(x))dfs(x+1);  42  }  43 }  44 void getni(){  45     for(int i=0;i<m;i++)D[i][i]=1;  46     for(int k=0;k<m;k++){  47         if(!C[k][k]){  48             for(int i=k+1;i<m;i++)if(C[i][k]){  49                 for(int j=0;j<m;j++){  50  swap(C[k][j],C[i][j]);  51  swap(D[k][j],D[i][j]);  52  }  53  }  54  }  55         int inv=qp(C[k][k],mod-2);  56         for(int i=0;i<m;i++){  57             C[k][i]=1ll*C[k][i]*inv%mod;  58             D[k][i]=1ll*D[k][i]*inv%mod;  59  }  60         for(int i=0;i<m;i++)if(i!=k&&C[i][k]){  61             int t=C[i][k];  62             for(int j=0;j<m;j++){  63                 UPD(C[i][j],mod-1ll*t*C[k][j]%mod);  64                 UPD(D[i][j],mod-1ll*t*D[k][j]%mod);  65  }  66  }  67  }  68 }  69 void dft(int n,int *f,int C[M][M]){  70     if(n==1)return ;  71     int l=n/m;  72     for(int i=0;i<m;i++)dft(l,f+i*l,C);  73     for(int i=0;i<n;i++)tmp[i]=0;  74     for(int i=0;i<m;i++)  75         for(int j=0;j<m;j++)  76             for(int k=0;k<l;k++)  77                 UPD(tmp[j*l+k],1ll*f[i*l+k]*C[i][j]%mod);  78     for(int i=0;i<n;i++)  79         f[i]=tmp[i];  80 }  81 int main(){  82 //freopen("test.in","r",stdin);
 83     for(int i=1,now;i<=22;i++){  84         w[i][0]=1;  85         now=qp(rt,(mod-1)/i);  86         for(int j=1;j<i;j++)  87             w[i][j]=1ll*w[i][j-1]*now%mod;  88  }  89     scanf("%d%d%lld",&n,&m,&K);  90     K=(K+1)%(mod-1);  91     for(int i=0;i<m;i++)  92         for(int j=0;j<m;j++)  93             scanf("%d",&A[i][j]);  94     for(int i=0;i<m;i++){  95         int now=i;  96         do{  97             cnt[i]++;  98             now=A[now][i];  99         }while(now!=i); 100  } 101     dfs(0); 102     all=qp(m,n); 103     for(int i=0;i<all;i++)scanf("%d",&f[i]); 104  dft(all,f,C); 105     for(int i=0;i<all;i++)f[i]=qp(f[i],K); 106  getni(); 107  dft(all,f,D); 108     for(int i=0;i<all;i++)printf("%d\n",f[i]); 109     return 0; 110 }
View Code
相關文章
相關標籤/搜索