zoukankan      html  css  js  c++  java
  • 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
    ",f[i]);
    109     return 0;
    110 }
    View Code
  • 相关阅读:
    求给定数组中最大值和其在数组中的索引并输出
    多线程与多进程
    logging模块
    QWidget上下文菜单处理函数
    python中的yield关键字
    菜单栏(QMenuBar)与菜单(QMenu)
    PyQt5布局管理(1)
    QMainFrame类
    QTP11使用DOM XPath以及CSS识别元素对象
    C# 跨线程访问控件
  • 原文地址:https://www.cnblogs.com/Ren-Ivan/p/8907173.html
Copyright © 2011-2022 走看看