loj548 「LibreOJ β Round #7」某少女附中的体育课

这道题好神啊!!!

发现这题就是定义了一种新的卷积,然后做k+1次卷积。

这里我们就考虑构造一个变换T,使得$T(a) \cdot T(b) =T(a∘b)$,这里是让向量右乘这个转移矩阵。

于是我们可以得到

$$\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}})$$

$$\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

 

posted @ 2018-04-23 21:36  Ren_Ivan  阅读(563)  评论(1编辑  收藏  举报