1. 程式人生 > >loj548 「LibreOJ β Round #7」某少女附中的體育課

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

dft col aps == ret hid 要求 但是 freopen

這道題好神啊!!!

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

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

於是我們可以得到

$$\sum_{j=0}^{m-1}{T_{j,i} \sum{[k \cdot 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}})$$

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

設x為T的某一列向量,這個變換滿足的條件就是$x_{j}x_{k}=x_{j°k}$

又因為循環律,設$c_{i}$為$i$的周期長度,我們發現$x_{i^{c_{i}}}=x_{i}^{c_{i}}=x_{i}$,所以$x_{i}=w_{c_{i}}^{k} or 0$。

之後我們發現合法的情況只有n種,考慮暴搜變換然後加上上面那個減枝就可以了。

然後我們就得到了我們要求的變換,然後就像fwt一樣每一維依次進行變換就可以了。

正解依舊沒有看懂,我的理解就是按照$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

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