1. 程式人生 > 其它 >[hdu7023]Yet Another Matrix Problem

[hdu7023]Yet Another Matrix Problem

關於$f(x)$的條件,將$C=A\times B$代入,即$\sum_{i=1}^{n}\sum_{j=1}^{n}\sum_{k=1}^{r}A_{i,k}B_{k,j}=x$

調換列舉順序,即$\sum_{k=1}^{r}(\sum_{i=1}^{n}A_{i,k})(\sum_{j=1}^{n}B_{k,j})=x$

顯然每一部分的值都是獨立的,因此令$G_{x}$​​為$(\sum_{i=1}^{n}A_{i,k})(\sum_{j=1}^{n}B_{k,j})=x$​​的方案數,列舉其中一項的值並對$x$​​是否為0分類討論,那麼不難得到有$G_{x}=\begin{cases}2(m+1)^{n}-1&(x=0)\\\sum_{d\mid x}{d+n-1\choose n-1}{\frac{x}{d}+n-1\choose n-1}&(x\ge 1)\end{cases}$​​​

令$G_{x}$對應的生成函式為$G(t)=\sum_{x\ge 0}G_{x}t^{x}$,那麼答案即為$[t^{x}]G^{r}(t)$(指$G^{r}(t)$的$x$​​次項係數),

根據調和級數,可以$o(m\log m)$​​求出$G_{x}$​​​,$G^{r}(t)$利用多項式求冪也可以做到$o(m\log m)$​​

最終,總複雜度為$o(m\log m)$​,可以通過

  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 #define N 200005
  4 #define L 18
  5 #define
mod 998244353 6 #define ll long long 7 #define vi vector<int> 8 #define Add(x,y) (x+y<mod ? x+y : x+y-mod) 9 #define Sub(x,y) (x>=y ? x-y : x-y+mod) 10 int t,n,m,fac[N],inv[N]; 11 vi v; 12 int C(int n,int m){ 13 return (ll)fac[n]*inv[m]%mod*inv[n-m]%mod; 14 } 15 int qpow(int
n,int m,int Mod=mod){ 16 int s=n,ans=1; 17 while (m){ 18 if (m&1)ans=(ll)ans*s%Mod; 19 s=(ll)s*s%Mod; 20 m>>=1; 21 } 22 return ans; 23 } 24 namespace Poly{ 25 int inv[1<<L],rev[1<<L],S[2][L][1<<L]; 26 void init(){ 27 inv[0]=inv[1]=1; 28 for(int i=2;i<(1<<L);i++)inv[i]=(ll)(mod-mod/i)*inv[mod%i]%mod; 29 for(int i=0;i<L;i++){ 30 int s=qpow(3,(mod-1>>i+1)),ss=qpow(s,mod-2); 31 S[0][i][0]=S[1][i][0]=1; 32 for(int j=1;j<(1<<i);j++){ 33 S[0][i][j]=(ll)s*S[0][i][j-1]%mod; 34 S[1][i][j]=(ll)ss*S[1][i][j-1]%mod; 35 } 36 } 37 } 38 vi Get(int num){ 39 vi ans; 40 ans.push_back(num); 41 return ans; 42 } 43 vi add(vi a,vi b,int n){ 44 a.resize(n); 45 for(int i=0;(i<n)&&(i<b.size());i++)a[i]=Add(a[i],b[i]); 46 return a; 47 } 48 vi sub(vi a,vi b,int n){ 49 a.resize(n); 50 for(int i=0;(i<n)&&(i<b.size());i++)a[i]=Sub(a[i],b[i]); 51 return a; 52 } 53 vi mul(vi a,int x,int n){ 54 a.resize(n); 55 for(int i=0;(i<n)&&(i<a.size());i++)a[i]=(ll)x*a[i]%mod; 56 return a; 57 } 58 vi Int(vi a,int n){ 59 a.resize(n); 60 for(int i=n-1;i;i--)a[i]=(ll)inv[i]*a[i-1]%mod; 61 a[0]=0; 62 return a; 63 } 64 vi derive(vi a,int n){ 65 a.resize(n); 66 for(int i=1;i<n;i++)a[i-1]=(ll)i*a[i]%mod; 67 a[n-1]=0; 68 return a; 69 } 70 void ntt(vi &a,int n,int p){ 71 for(int i=0;i<n;i++) 72 if (i<rev[i])swap(a[i],a[rev[i]]); 73 for(int i=2,ii=0;i<=n;i<<=1,ii++) 74 for(int j=0;j<n;j+=i) 75 for(int k=0;k<(i>>1);k++){ 76 int x=a[j+k],y=(ll)S[p][ii][k]*a[j+k+(i>>1)]%mod; 77 a[j+k]=Add(x,y),a[j+k+(i>>1)]=Sub(x,y); 78 } 79 if (p)a=mul(a,qpow(n,mod-2),n); 80 } 81 vi mul(vi a,vi b,int n){ 82 int m=0; 83 while ((1<<m)<min(n,(int)a.size())+min(n,(int)b.size()))m++; 84 m=(1<<m),a.resize(m),b.resize(m); 85 for(int i=n;i<m;i++)a[i]=b[i]=0; 86 for(int i=0;i<m;i++)rev[i]=(rev[i>>1]>>1)+(i&1)*(m>>1); 87 ntt(a,m,0),ntt(b,m,0); 88 for(int i=0;i<m;i++)a[i]=(ll)a[i]*b[i]%mod; 89 ntt(a,m,1); 90 while (a.size()>n)a.pop_back(); 91 return a; 92 } 93 vi Inv(vi a,int n){ 94 if (n==1)return Get(qpow(a[0],mod-2)); 95 vi ans=Inv(a,n+1>>1); 96 return sub(mul(ans,2,n),mul(a,mul(ans,ans,n),n),n); 97 } 98 vi ln(vi a,int n){ 99 return Int(mul(derive(a,n),Inv(a,n),n),n); 100 } 101 vi exp(vi a,int n){ 102 if (n==1)return Get(1); 103 vi ans=exp(a,n+1>>1); 104 return mul(ans,sub(add(a,Get(1),n),ln(ans,n),n),n); 105 } 106 vi Qpow(vi a,int n,int m,int mm){ 107 int s=a[0]; 108 assert(s); 109 a=mul(a,qpow(s,mod-2),n); 110 return mul(exp(mul(ln(a,n),m,n),n),qpow(s,mm),n); 111 } 112 } 113 int main(){ 114 fac[0]=inv[0]=inv[1]=1; 115 for(int i=1;i<N;i++)fac[i]=(ll)fac[i-1]*i%mod; 116 for(int i=2;i<N;i++)inv[i]=(ll)(mod-mod/i)*inv[mod%i]%mod; 117 for(int i=1;i<N;i++)inv[i]=(ll)inv[i-1]*inv[i]%mod; 118 Poly::init(); 119 scanf("%d",&t); 120 while (t--){ 121 scanf("%d%d",&n,&m); 122 v.clear(),v.resize(++m); 123 v[0]=(2*qpow(m,n)-1)%mod; 124 for(int i=1;i<m;i++) 125 for(int j=i;j<m;j+=i)v[j]=(v[j]+(ll)C(i+n-1,n-1)*C(j/i+n-1,n-1))%mod; 126 v=Poly::Qpow(v,m,qpow(n,m-1),qpow(n,m-1,mod-1)); 127 for(int i=0;i<m;i++)printf("%d\n",v[i]); 128 } 129 return 0; 130 }
View Code