[atARC084F]XorShift
如果异或变为加法和减法,那么根据扩欧,$k$合法当且仅当$k|\gcd_{i=1}^{n}a_{i}$
换一种方式定义约数:$x$是$y$的约数当且仅当存在$p_{i}\in \{0,1\}$使得$\sum_{i=0}^{\infty}2^{i}x=y$,那么类似的,再把加法改为异或,我们就得到了本题中关于约数的定义
如何求$d=\gcd(x,y)$:假设$x$的最高位为$2^{p}$,$y$的最高位为$2^{q}$(二进制下,且不妨假设$p\ge q$),那么有$d|x$和$d|2^{p-q}y$,又因为$d|x$,所以$d|(x\oplus 2^{p-q}y)$,即$\gcd(x,y)=\gcd(y,x-2^{p-q}y)$
对于求gcd的过程,每一次必然会使得最高位-1,可以通过bitset优化到$o(\frac{nL^{2}}{64})$
令$d=\gcd_{i=1}^{n}a_{i}$,考虑$k\le C$等价于$k\oplus C$的最高位上的1是$C$的1或$k\oplus C$为0,因此枚举$k\oplus C$第一个非0的位置(通过$p_{i}$来控制),最后再判断所有$p_{i}$都确定了(即$k\oplus C$在$d$最高位即以上都为0时)能否即可
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define N 4005 4 #define mod 998244353 5 struct ji{ 6 int l; 7 bitset<N>a; 8 }m,a[11]; 9 int n,ans,mi[N]; 10 char s[N]; 11 void read(ji &a){ 12 scanf("%s",s); 13 a.l=strlen(s); 14 for(int i=0;i<a.l;i++)a.a[a.l-i]=s[i]-'0'; 15 } 16 ji gcd(ji x,ji y){ 17 if (!y.l)return x; 18 x.a^=(y.a<<x.l-y.l); 19 while ((x.l)&&(!x.a[x.l]))x.l--; 20 if (x.l<y.l)swap(x,y); 21 return gcd(x,y); 22 } 23 void write(ji a){ 24 for(int i=a.l;i;i--){ 25 int p=a.a[i]; 26 printf("%d",p); 27 } 28 printf("\n"); 29 } 30 int main(){ 31 mi[0]=1; 32 for(int i=1;i<N-4;i++)mi[i]=mi[i-1]*2%mod; 33 scanf("%d",&n); 34 read(m); 35 read(a[1]); 36 for(int i=2;i<=n;i++){ 37 read(a[i]); 38 if (a[1].l<a[i].l)swap(a[1],a[i]); 39 a[1]=gcd(a[1],a[i]); 40 } 41 if (m.l<a[1].l){ 42 printf("1"); 43 return 0; 44 } 45 ji s=m; 46 for(int i=m.l;i>=a[1].l;i--){ 47 if (m.a[i])ans=(ans+mi[i-a[1].l])%mod; 48 if (s.a[i])s.a^=(a[1].a<<i-a[1].l); 49 } 50 ans=(ans+1)%mod; 51 for(int i=a[1].l-1;i;i--) 52 if (s.a[i]){ 53 if (!m.a[i])ans=(ans+mod-1)%mod; 54 break; 55 } 56 printf("%d",ans); 57 }