題目大意:
給兩個數列${B_i}、{C_i}$,長度均為$n$,且${B_i}$循環移位線性無關,即不存在一組系數${X_i}$使得對於所有的$k$均有$\sum_{i=0}^{n-1} X_i B_{k-i \mod n} =0$。
已知$C$是由$B$與$A$構造得到:
(搬原圖)。
求所有合法的$A$序列。
題解:
首先把式子稍加化簡會得到:
顯然是個差分式,然后就會得到以下兩種結果(以下$B_{i}$均為$B_{i\mod n}$):
問題是,這兩個式子都是對的嗎?
顯然不是。
我們考慮題目中說的${B_i}$為循環移位線性無關,但是$\Delta B_i=B_{i+1}-B_{i}$構成的${\Delta B_{i}}$我們是不知道它是否是線性無關的,如果是線性無關,那么它是正確的,反之,我們會知道必然存在一組${X_i}$使得若${A}$有解,則有無窮解,但是回帶是錯誤的。
但是二式我們如果可以求解可知$\Delta A_i=A_{i+1}-A{i}$是有唯一解的,然后考慮回帶求$A_0$我們就可以得到最多兩個解。
所以本題就變成了求:
設$B'_i=B_{-i}$,即:
即,問題變為求出$\Delta C$的點值然后除去$B'_{*Z/n}$的點值再除去$-2$我們再由$\Delta A$的點值求出其系數即可。
當然,我們可以知道$\Delta A$的系數小於$2e3$,所以我們防止卡精使用$NTT$。
由於並不知道$B'_{*Z/n}$的長度,所以不能裸上,需要使用Bluestein's Algorithm。
這個東西網上幾乎沒有講解,好像毛爺爺的《再探》里面有說?
具體就是:
這樣就可以使用一次卷積來求$B'$的點值了。($NTT$並不能直接拆成上面的形式,因為數論變換是沒法消去下面除的那個2)
所以將$ik$變為然后拆解即可。
代碼:

1 #include "bits/stdc++.h" 2 3 typedef long long ll; 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 const int N=6e5+10; 13 14 ll mod,g,w[2][N],W[2][N]; 15 16 inline ll Mult ( ll a,ll b ) { 17 return ( a*b - (ll)( (long double) a*b/mod )*mod + mod )% mod; 18 } 19 20 inline ll powmod ( ll a, ll b ) { 21 ll ret=1; 22 while (b) { 23 if (b&1) ret=Mult ( ret, a ); 24 b>>=1,a=Mult ( a, a); 25 }return ret; 26 } 27 28 inline ll gcd ( ll a,ll b ) { return b?gcd(b,a%b) : a; } 29 30 int n,m; 31 32 inline void Get_mod () { 33 for (m=1; (m<=2*n) ;m<<=1 ); 34 ll lcm =1ll* n*m /gcd (n,m); 35 mod = lcm + 1; 36 while ( mod < 1e5 ) mod += lcm; 37 while (1) { 38 int flag=true; 39 for (int i=2;1ll*i*i<=mod;++i) if (mod%i==0) {flag=false;break;} 40 if (flag) break; 41 mod+=lcm; 42 } 43 for (g=2;;++g) { 44 int flag=true; 45 for (int i=2;1ll*i*i<=mod;++i) if ((mod-1)%i==0){ 46 if (powmod(g,i)==1) {flag=false;break;} 47 if (powmod(g,(mod-1)/i)==1) {flag=false;break;} 48 } 49 if (flag) break; 50 } 51 } 52 53 inline void Get_wn(){ 54 ll w0=powmod(g,(mod-1)/m); 55 w[0][0]=w[1][0]=1; 56 int i; 57 for (i=1;i<m;++i) w[0][i]=Mult(w[0][i-1],w0); 58 for (i=1;i<m;++i) w[1][i]=w[0][m-i]; 59 w0=powmod(g,(mod-1)/n); 60 W[0][0]=W[1][0]=1; 61 for (i=1;i<n;++i) W[0][i]=Mult(W[0][i-1],w0); 62 for (i=1;i<n;++i) W[1][i]=W[0][n-i]; 63 } 64 65 inline void NTT(ll *a,int n,int f) { 66 register int i,j,k,l,t; 67 for (i=j=0;i^n;++i) { 68 if (i>j) std::swap(a[i],a[j]); 69 for (k=n>>1;(j^=k)<k;k>>=1); 70 } 71 for (i=1;i<n;i<<=1) 72 for (j=0,t=n/(i<<1);j<n;j+=i<<1) 73 for (k=l=0;k<i;++k , l+=t ) { 74 ll x=a[j+k],y=Mult(a[i+j+k],w[f][l]); 75 a[j+k]=x+y; 76 a[i+j+k]=x-y; 77 if (a[j+k]>=mod) a[j+k]-=mod; 78 if (a[i+j+k]<0) a[i+j+k]+=mod; 79 } 80 if (f ) { 81 ll rev=powmod ( n,mod-2 ); 82 for (i=0;i<n;++i) a[i]=Mult(a[i],rev); 83 } 84 } 85 86 ll Y[N]; 87 88 inline void pre_Bluestein(int f) { 89 int i; 90 for (i=0;i<2*n;++i) Y[2*n-1-i]=W[f][1ll*i*(i-1)/2%n]; 91 for (i=2*n;i<m;++i) Y[i]=0; 92 NTT(Y,m,0); 93 } 94 95 inline void Bluestein(ll *a,int f){ 96 static ll X[N]; 97 register int i; 98 for (i=0;i<n;++i) X[i]=Mult(a[i],W[f][ (n-1ll*i*(i-1)/2%n)%n ]); 99 for (i=n;i<m;++i) X[i]=0; 100 NTT(X,m,0); 101 for (i=0;i<m;++i) X[i]=Mult(X[i],Y[i]); 102 NTT(X,m,1); 103 for (i=0;i<n;++i) 104 a[i]=Mult (X[2*n-1-i],W[f][(n-1ll*i*(i-1)/2%n)%n ]); 105 if (f) { 106 ll rev=powmod(n,mod-2); 107 for (i=0;i<n;++i) a[i]=Mult(a[i],rev); 108 } 109 } 110 111 int b[N],c[N]; 112 ll rev_b[N],delta_c[N],delta_a[N],a[N]; 113 114 int main() { 115 //freopen(".in","r",stdin); 116 n = read(); 117 register int i; 118 for (i=0;i<n;++i) b[i]=read(); 119 for (i=0;i<n;++i) c[i]=read(); 120 Get_mod(); 121 Get_wn(); 122 for (i=0;i<n;++i) rev_b[i]=b[i]; 123 std::reverse(rev_b+1,rev_b+n); 124 ll inv_2=powmod(mod-2,mod-2); 125 for (i=0;i<n;++i) delta_c[i]=Mult ( ( c[(i+1)%n]-c[i] + mod )%mod , inv_2 ); 126 pre_Bluestein(0); 127 Bluestein(rev_b,0); 128 Bluestein(delta_c,0); 129 for (i=0;i<n;++i) delta_a[i]=Mult ( delta_c[i] , powmod (rev_b[i],mod-2) ); 130 pre_Bluestein(1); 131 Bluestein(delta_a,1); 132 for (i=0;i<n;++i) { 133 ll v=(delta_a[i]<mod-delta_a[i])?delta_a[i]:delta_a[i]-mod; 134 if (abs(v)>20000) return puts("0"),0; 135 a[i]=v; 136 } 137 ll _c=-c[0],_a=0,_b=0,sum=0; 138 for (i=0;i<n;++i) { 139 ++_a; 140 _b+=2*(sum-b[i]); 141 _c+=(sum-b[i])*(sum-b[i]); 142 sum+=a[i]; 143 } 144 if (sum!=0) { 145 puts("0"); 146 return 0; 147 } 148 std::set<ll> ans; 149 if (_b*_b-4*_a*_c>=0){ 150 ll s=ll(sqrt(_b*_b-4*_a*_c) + 0.5); 151 if (s*s!=_b*_b-4*_a*_c) return puts("0"),0; 152 if ((-_b+s)%(2*_a)==0) ans.insert((-_b+s)/(2*_a)); 153 if ((-_b-s)%(2*_a)==0) ans.insert((-_b-s)/(2*_a)); 154 } 155 std::set<ll>::iterator it; 156 printf("%d\n",ans.size()); 157 for (it=ans.begin();it!=ans.end();++it) { 158 ll now=*it; 159 for (i=0;i<n;++i){ 160 printf("%lld ",now); 161 now+=a[i]; 162 } 163 puts(""); 164 } 165 }