「CodeChef Dec13 REALSET」 Petya and Sequence 循环卷积

题目大意:

  传送门

  T组询问。

  每组给一个数组,询问该数组是否循环移位线性无关,输出YES或NO。

题解:

  LCA冬令营有讲……然而当时……

  并不知道如何计算一个数组是否循环移位线性无关……网上也没有……学校还加了白名单,翻不了墙,看不了wiki(英文看不懂……)。所以这就是我怂题解的理由23333。

  题解上说wiki上循环矩阵的行列式等于其DFT后点值乘积。即对于矩阵:

  

  有:

  

  显然如果循环数组的矩阵的轶不为n的话其行列式必然为0。

  所以把数组DFT以后看一下其乘积是否为0即可。

  证明什么的……留个坑吧。

  看到了一个大神打了几十行……没看懂在干什么……

  LCA说还可以用分圆多项式,然而并没有找到资料。再留个坑吧……

代码:

  1 #include "bits/stdc++.h"
  2  
  3 using std::swap;
  4  
  5 inline int read () {
  6     int s=0,k=1;char ch=getchar();
  7     while (ch<'0'|ch>'9') ch=='-'?k=-1:0,ch=getchar();
  8     while (ch>47&ch<='9') s=s*10+(ch^48),ch=getchar();
  9     return s*k;
 10 }
 11  
 12 typedef long long ll;
 13  
 14 const int N=1e5+10;
 15  
 16 ll mod,g,w[2][N],W[2][N],n,m;
 17  
 18 inline ll gcd (ll a,ll b) {
 19     return b?gcd(b,a%b):a;
 20 }
 21  
 22 inline ll Mult ( ll a,ll b ) {
 23     return ( a*b - (ll)( (long double) a*b/mod )*mod + mod )% mod;
 24 }
 25  
 26 inline ll powmod ( ll a, ll b ) {
 27     ll ret=1;
 28     while (b) {
 29         if (b&1) ret=Mult ( ret, a );
 30         b>>=1,a=Mult ( a, a);
 31     }return ret;
 32 }
 33  
 34 inline int is_prim(ll x) {
 35     for (int i=2;1ll*i*i<=x;++i)
 36         if (x%i==0) return false;
 37     return true;
 38 }
 39  
 40 inline int is_prim_root(ll x,ll y){
 41     for (int i=1;1ll*i*i<y;++i)
 42         if ((y-1)%i==0) {
 43             if (powmod(x,i)==1) return false;
 44             if (powmod(x,(y-1)/i)==1)return false;
 45         }
 46     return true;
 47 }
 48  
 49 inline void init () {
 50     for (m=1;m<=2*n;m<<=1);
 51     ll lcm = n*m/gcd(n,m);
 52     mod = lcm + 1;
 53     for (int i=30;~i;--i)
 54         if (mod + (lcm<<i)<1e3*n) mod+=lcm<<i;
 55     while (mod<1e3*n) mod+=lcm;
 56     while (!is_prim(mod))  mod+=lcm;
 57     for (g=2;;++g) {
 58         int flag=true;
 59         for (int i=2;1ll*i*i<=mod;++i) if ((mod-1)%i==0){
 60             if (powmod(g,i)==1) {flag=false;break;}
 61             if (powmod(g,(mod-1)/i)==1) {flag=false;break;}
 62         }
 63         if (flag) break;
 64     }
 65     
 66     ll w0=powmod(g,(mod-1)/m);
 67     w[0][0]=w[1][0]=1;
 68     int i;
 69     for (i=1;i<m;++i) w[0][i]=Mult(w[0][i-1],w0);
 70     for (i=1;i<m;++i) w[1][i]=w[0][m-i];
 71     w0=powmod(g,(mod-1)/n);
 72     W[0][0]=W[1][0]=1;
 73     for (i=1;i<n;++i) W[0][i]=Mult(W[0][i-1],w0);
 74     for (i=1;i<n;++i) W[1][i]=W[0][n-i];
 75 }
 76  
 77  
 78 inline void NTT(ll *a,int n,int f) {
 79     register int i,j,k,l,t;
 80     for (i=j=0;i^n;++i) {
 81         if (i>j) std::swap(a[i],a[j]);
 82         for (k=n>>1;(j^=k)<k;k>>=1);
 83     }
 84     for (i=1;i<n;i<<=1) 
 85         for (j=0,t=n/(i<<1);j<n;j+=i<<1) 
 86             for (k=l=0;k<i;++k , l+=t ) {
 87                 ll x=a[j+k],y=Mult(a[i+j+k],w[f][l]);
 88                 a[j+k]=x+y;
 89                 a[i+j+k]=x-y;
 90                 if (a[j+k]>=mod) a[j+k]-=mod;
 91                 if (a[i+j+k]<0) a[i+j+k]+=mod;
 92             }
 93     if (f ) {
 94         ll rev=powmod ( n,mod-2 );
 95         for (i=0;i<n;++i) a[i]=Mult(a[i],rev);
 96     }
 97 }
 98  
 99  
100 inline void Bluesteins(ll *a,int f){
101     static ll X[N],Y[N];
102     register int i;
103     for (i=0;i<2*n;++i) Y[2*n-1-i]=W[f][1ll*i*(i-1)/2%n];
104     for (i=2*n;i<m;++i) Y[i]=0;
105     NTT(Y,m,0);
106     for (i=0;i<n;++i) X[i]=Mult(a[i],W[f][ (n-1ll*i*(i-1)/2%n)%n ]);
107     for (i=n;i<m;++i) X[i]=0;
108     NTT(X,m,0);
109     for (i=0;i<m;++i) X[i]=Mult(X[i],Y[i]);
110     NTT(X,m,1);
111     for (i=0;i<n;++i)
112         a[i]=Mult (X[2*n-1-i],W[f][(n-1ll*i*(i-1)/2%n)%n ]);
113     if (f)  {
114         ll rev=powmod(n,mod-2);
115         for (i=0;i<n;++i) a[i]=Mult(a[i],rev);
116     }
117 }
118 
119 ll a[N];
120  
121 int main (int argc, char const* argv[]){    
122     //freopen("Dec13Realset.in","r",stdin);
123     int T=read(),i;
124     while (T-- ){
125         n=read();
126         for (i=0;i<n;++i) a[i]=read();
127         init();
128         Bluesteins(a,0);
129         ll flag=1;
130         for (i=0;i<n;++i) flag=Mult(flag,a[i]);
131         puts(flag?"NO":"YES");
132     }
133     return 0;
134 }

 

posted @ 2018-05-03 21:25  Troywar  阅读(368)  评论(0编辑  收藏