A:CF1119H加强版,k<=10。
不太想解释。
1 #define mod 998244353 2 #define G2 499122177 3 #include<bits/stdc++.h> 4 using namespace std; 5 typedef long long int ll; 6 int n,m,k,a[55],p[1000005][11],mask; 7 ll f[1<<21],**g,val[1<<21]; 8 inline ll qpow(ll x,ll y) 9 { 10 ll ans=1,base=x; 11 while(y) 12 { 13 if(y&1) 14 ans=ans*base%mod; 15 base=base*base%mod; 16 y>>=1; 17 } 18 return ans; 19 } 20 inline void FWT(ll*A,int limit) 21 { 22 for(int len=2;len<=limit;len<<=1) 23 for(int i=0;i<limit/len;++i) 24 for(int j=0;j<len/2;++j) 25 { 26 ll x=A[i*len+j],y=A[i*len+j+len/2]; 27 A[i*len+j]=(x+y)%mod; 28 A[i*len+j+len/2]=(x-y+mod)%mod; 29 } 30 } 31 inline void IFWT(ll*A,int limit) 32 { 33 for(int len=2;len<=limit;len<<=1) 34 for(int i=0;i<limit/len;++i) 35 for(int j=0;j<len/2;++j) 36 { 37 ll x=A[i*len+j],y=A[i*len+j+len/2]; 38 A[i*len+j]=(x+y)%mod*G2%mod; 39 A[i*len+j+len/2]=(x-y+mod)%mod*G2%mod; 40 } 41 } 42 int main() 43 { 44 ios::sync_with_stdio(false); 45 cin>>n>>m; 46 k=3; 47 for(int i=0;i<k;++i) 48 cin>>a[i]; 49 for(int i=1;i<=n;++i) 50 { 51 for(int j=0;j<k;++j) 52 cin>>p[i][j]; 53 mask^=p[i][0]; 54 for(int j=1;j<k;++j) 55 p[i][j]^=p[i][0]; 56 } 57 g=new ll*[1<<m]; 58 for(int i=0;i<(1<<m);++i) 59 { 60 g[i]=new ll[1<<(k-1)]; 61 for(int j=0;j<(1<<(k-1));++j) 62 g[i][j]=0; 63 g[i][0]=n; 64 } 65 for(int i=0;i<k;++i) 66 val[0]=(val[0]+a[i])%mod; 67 for(int S=1;S<(1<<(k-1));++S) 68 { 69 for(int i=0;i<(1<<m);++i) 70 f[i]=0; 71 val[S]=a[0]; 72 for(int j=0;j<k-1;++j) 73 if(S&(1<<j)) 74 val[S]=(val[S]-a[j+1]+mod)%mod; 75 else 76 val[S]=(val[S]+a[j+1])%mod; 77 for(int i=1;i<=n;++i) 78 { 79 int s=0; 80 for(int j=0;j<k-1;++j) 81 if(S&(1<<j)) 82 s^=p[i][j+1]; 83 ++f[s]; 84 } 85 FWT(f,1<<m); 86 for(int i=0;i<(1<<m);++i) 87 g[i][S]=f[i]; 88 } 89 ll G=qpow(1<<(k-1),mod-2); 90 for(int i=0;i<(1<<m);++i) 91 { 92 IFWT(g[i],1<<(k-1)); 93 ll ans=1; 94 for(int S=0;S<(1<<(k-1));++S) 95 ans=ans*qpow(val[S],g[i][S])%mod; 96 f[i]=ans; 97 } 98 IFWT(f,1<<m); 99 for(int i=0;i<(1<<m);++i) 100 cout<<f[i^mask]<<" "; 101 cout<<endl; 102 return 0; 103 }
B:给一个n*m的矩阵,一行一行从左到右编号依次加一直到n*m。有如下操作:
1.交换x、y行。
2.交换x、y列。
3.询问某一个子矩阵的k次前缀和的和。
n,m,q<=100000,k<=10。
我们不可能直接维护整个矩阵,所以一定是把矩阵拆成两维分别维护。
原来的第i行j列的值是$(i-1)*m+j$,我们可以把它理解成$a_i+b_j$。交换某一行或某一列时,相当于交换$a$或$b$中的两个元素。
观察子矩阵中的每一个元素对于一个询问的贡献,可以发现每个格子的系数相当于从这个格子出发走$k+1$步到达右下角(即$(x_2,y_2)$)的方案数,每次可以走到两维坐标都大于等于它的一个格子(包括自己)。由此可知两维系数是独立的,对于一个格子$(i,j)$其系数可以写成$c_i*d_j$的形式,因为格子的两维坐标增大是互不影响的。而$c_i,d_i$就是在一维的坐标中,每次往右走若干步,走$k+1$次走到某一个端点的方案数。用插板法可得其为$\binom{x+k}{k}$,其中$x$是到这个端点的距离。
最终的答案是
$$
\sum_{i=x1}^{x2}\sum_{j=y1}^{y2}c_id_j(a_i+b_j)
$$
$$
=(\sum_{i=x1}^{x2}c_ia_i)(\sum_{j=y1}^{y2}d_j)+(\sum_{i=x1}^{x2}c_i)(\sum_{j=y1}^{y2}d_jb_j)
$$
暴力计算这个式子,一个询问就可以$O(n+m)$求出答案。
易得$c_i=\binom{k+x_2-i}{k}=\frac{(k+x_2-i)!}{k!(x2-i)!}=\frac{1}{k!}(k+x_2-i)^{\underline{k}}$
我们知道
$$
x^{\underline{n}}=\sum_{i=0}^n(-1)^{n-i}s(n,i)x^i
$$
其中$s(n,i)$是第一类斯特林数
将这个下降幂套进去
$$
(k+x_2-i)^{\underline{k}}=\sum_{d=0}^k(-1)^{k-d}s(k,d)(k+x_2-i)^d
$$
$$
=\sum_{d=0}^k(-1)^{k-d}s(k,d)\sum_{e=0}^d\binom{d}{e}(x_2+k)^e(-i)^{d-e}
$$
如果把$x_2,k$看成参数,这是一个关于$i$的$k$次多项式。
我们只要对于0~10维护$\sum a_i\times i^k$就好了(当然,有些细节不同,仍需推式子)。对于另一维同理。修改就是交换$a_x,a_y$。
其实我们不需要推式子,我们只要知道系数是关于$i$的$k$次多项式,你可以暴力拆解所有的因式,就可以得到这些系数。
$c_i=\binom{k+x_2-i}{k}=\frac{(k+x_2-i)!}{k!(x2-i)!}=\frac{1}{k!}(k+x_2-i)^{\underline{k}}$
展开这个下降幂,可得
$(k+x_2-i)^{\underline{k}}=(k+x_2-i)(k+x_2-i-1)(k+x_2-i-2)...$
将其看成关于$i$和$x_2$的二元多项式,对于每个k预处理一下这些多项式每一项的系数,询问时把$x_2$代进去。
一次修改复杂度是$O(klogn)$的,询问是$O(k^2+klogn)$的
C:有如下代码:
void add_fish(long long &cnt, long long x, long long len) { long long y = x % len; while(h[y] != -1 && h[y] != x) y = (y + 1) % len, cnt ++; h[y] = x; } long long solve(long long len) { for(int i = 0; i < len; i ++) h[i] = -1; long long cnt = 0; for(int i = 1; i <= n; i ++) add_fish(cnt, a[i], len); return cnt; }
现在给出数组a,问在long long范围内,solve的返回值最大为多少?