BZOJ上数据范围没写清楚,实际数据范围如这个表格所示。
把$M_n$和$x$看成$\mathbb{F}_2$下的$m$维的列向量,则有转移矩阵 $$A = \begin{pmatrix} 0 & 0 & \cdots & 0 & -x_0\\ 1 & 0 & \cdots & 0 & -x_1\\ 0 & 1 & \cdots & 0 & -x_2\\ \vdots & \vdots & \ddots & \vdots & \vdots\\ 0 & 0 & \cdots & 1 & -x_{m-1}\\ \end{pmatrix}$$ 该矩阵为多项式 $$p(z) = z^m+\sum_{i=0}^{m-1}x_iz^i$$ 的友阵。因此,若把$M_n$看成$F$中的元素,则有 $$M_n(z) = z^nM_0(z)$$ 其中$F = \mathbb{F}_2[z]/(p(z))$为模$p(z)$意义下的$\mathbb{F}_2$上的多项式构成的环。当然,也可以直接通过观察得出这个结论。注意到$n < m$时$F$中的$z^n$与$\mathbb{F}_2[z]$中的相同,于是可以以复杂度 $$O\bigl(m\log m\max(1,\log k-\log m)\bigr)$$ 解决第一种情况。
所有$2^m-1$个非零元素都能被生成,是数列在这些元素中等概率取值的必要条件。该条件成立时有 $$\begin{aligned} 2^m-1 &= |\mathopen{<}z\mathclose{>}M_0(z)| = |\mathopen{<}z\mathclose{>}|\\ &\le |F^\times| \le |F \setminus \{0\}| = 2^m-1 \end{aligned}$$ 其中$F^\times$为$F$中所有有乘法逆元的元素构成的乘法群。由此得$\mathopen{<}z\mathclose{>} = F^\times = F \setminus \{0\}$,那么$F$为大小为$2^m$的有限域,且$\forall f(z) \in F^\times$,有$(f(z))^{2^m} = f(z)$,故 $$\begin{aligned} M_k(z) &= (z^{k \cdot 2^l})^{2^{m-l}}M_0(z)\\ &= \Bigl(M_{k \cdot 2^l}(z)\bigl(M_0(z)\bigr)^{-1}\Bigr)^{2^{m-l}}M_0(z)\\ &= \bigl(M_{k \cdot 2^l}(z)\bigr)^{2^{m-l}}\Bigl(\bigl(M_0(z)\bigr)^{2^{m-l}}\Bigr)^{2^l-1}\\ \end{aligned}$$ 从而可以以复杂度$O(m^2\log m)$解决第二种情况。
由上述推导可知,$x$是好的等价于$F$是一个域,且$z$是$F^\times$的生成元。$F$是一个域当且仅当$p(z)$是$\mathbb{F}_2$上的既约多项式。由此,或许可以用某些方法生成第二种情况的数据。
这题挺好写的,就一多项式除法就没了,不知道为啥没几个人写。
#include<algorithm>
#include<vector>
#include<cstdio>
#define RAN(a)a.begin(),a.end()
using namespace std;
typedef unsigned long long u64;
typedef unsigned u32;
namespace num{
const u32 p=1811939329;
const u32 g=13;
inline u32 imod(u32 a){
return a<p?a:a-p;
}
inline u32 ipow(u32 a,u32 n){
u32 s=1;
for(;n;n>>=1){
if(n&1)
s=(u64)s*a%p;
a=(u64)a*a%p;
}
return s;
}
inline u32 inv(u32 a){
return ipow(a,p-2);
}
}
using namespace num;
class poly_base{
public:
vector<u32>a;
poly_base(){}
explicit poly_base(int n):a(n){}
void fft(int n,bool f){
a.resize(n);
if(n<=1)
return;
for(int i=0,j=0;i<n;++i){
if(i<j)
std::swap(a[i],a[j]);
int k=n>>1;
while((j^=k)<k)
k>>=1;
}
vector<u32>w(n/2);
w[0]=1;
for(int i=1;i<n;i<<=1){
for(int j=i/2-1;~j;--j)
w[j<<1]=w[j];
int m=(p-1)/i/2;
u64 s=ipow(g,f?p-1-m:m);
for(int j=1;j<i;j+=2)
w[j]=s*w[j-1]%p;
for(int j=0;j<n;j+=i<<1){
u32*b=&a[0]+j,*c=b+i;
for(int k=0;k<i;++k){
u32 v=(u64)w[k]*c[k]%p;
c[k]=imod(b[k]+p-v);
b[k]=imod(b[k]+v);
}
}
}
}
void dft(int n){
fft(n,0);
}
void idft(){
int n=a.size();
fft(n,1);
u64 f=inv(n);
for(int i=0;i<n;++i)
a[i]=f*a[i]%p;
}
};
class poly:public poly_base{
public:
poly(){}
explicit poly(int n):poly_base(n){}
u32&operator[](int i){
return a[i];
}
const u32&operator[](int i)const{
return a[i];
}
int size()const{
return a.size();
}
void swap(poly&b){
a.swap(b.a);
}
static int len(int n){
while(n^n&-n)
n+=n&-n;
return n;
}
void fix(){
while(size()&&!a.back())
a.pop_back();
}
void mul(poly b){
fix();
b.fix();
int n=len(size()+b.size()-1);
dft(n);
b.dft(n);
for(int i=0;i<n;++i)
a[i]=(u64)a[i]*b[i]%p;
idft();
for(int i=0;i<n;++i)
a[i]&=1;
fix();
}
void sqr(){
fix();
int n=len(2*size()-1);
dft(n);
for(int i=0;i<n;++i)
a[i]=(u64)a[i]*a[i]%p;
idft();
for(int i=0;i<n;++i)
a[i]&=1;
fix();
}
void mod(int n){
a.resize(n);
}
void inv(int n){
int m=len(n);
mod(m);
vector<u32>b(1,1);
a.swap(b);
for(int i=2;i<=m;i<<=1){
poly c(i);
for(int j=0;j<i;++j)
c[j]=b[j];
sqr();
mul(c);
mod(i);
}
mod(n);
}
void div(poly b){
fix();
b.fix();
int n=size()-b.size()+1;
if(n<=0){
a.clear();
return;
}
reverse(RAN(a));
mod(n);
reverse(RAN(b.a));
b.inv(n);
mul(b);
mod(n);
reverse(RAN(a));
fix();
}
void mod(poly b){
fix();
b.fix();
int m=b.size();
if(size()>=m){
poly c=*this;
div(b);
mul(b);
mod(m-1);
for(int i=0;i<m-1;++i)
a[i]^=c[i];
fix();
}
}
};
struct ano{
operator u64(){
u64 x=0;
signed c=getchar();
while(c<48)
c=getchar();
while(c>47)
x=x*10+c-48,c=getchar();
return x;
}
}buf;
poly basis(int n){
poly a(n+1);
a[n]=1;
return a;
}
int main(){
int n=buf;
poly p(n+1);
p[n]=1;
for(int i=0;i<n;++i)
p[i]=buf;
poly s(n);
for(int i=0;i<n;++i)
s[i]=buf;
if(buf==0){
u64 k=buf;
if(k<n){
s.mul(basis(k));
s.mod(p);
}else{
int i=0;
while((k&(2<<i)-1)<n)
++i;
s.mul(basis(k&(1<<i)-1));
s.mod(p);
poly a=basis(1<<i);
k>>=i;
for(;k;k>>=1){
if(k&1){
s.mul(a);
s.mod(p);
}
if(k>1){
a.sqr();
a.mod(p);
}
}
}
}else{
int l=buf%n;
poly a(n);
for(int i=0;i<n;++i)
a[i]=buf;
s.swap(a);
for(int i=0;i<n-l;++i){
s.sqr();
s.mod(p);
a.sqr();
a.mod(p);
}
for(int i=0;i<l;++i){
s.mul(a);
s.mod(p);
if(i<l-1){
a.sqr();
a.mod(p);
}
}
}
s.mod(n);
for(int i=0;i<n;++i)
printf("%d",s[i]);
puts("");
}
Rewrited @ 姫野星奏生誕祭2019
Edited @ 2019-06-28