- 典型的計數DP。利用問題的可劃分性和子問題之間的相似性,把問題視作若干個重疊子問題的逐層遞進。按位劃分階段。
- 鞏固了用vector儲存多項式的思想
點選檢視程式碼
#include <bits/stdc++.h>
using namespace std;
const int mod=998244353;
int power(int n,int p)
{
if(p==0)
{
return 1;
}
long long tmp=power(n,p/2);
if(p%2==1)
{
return tmp*tmp%mod*n%mod;
}
return tmp*tmp%mod;
}
long long k,jc[205],jcinv[205];
void pre()
{
jc[0]=1;
for(int i=1;i<=200;i++)
{
jc[i]=jc[i-1]*i%mod;
}
jcinv[200]=power(jc[200],998244351);
for(int i=200-1;i>=0;i--)
{
jcinv[i]=jcinv[i+1]*(i+1)%mod;
}
}
long long C(int n,int m)
{
return jc[n]*jcinv[m]%mod*jcinv[n-m]%mod;
}
vector<long long> calc(vector<long long>A,vector<long long>B,int id)
{
vector<long long>a[2],b[2],c[2],ans(min(A.size(),B.size())+1);
if(id<0)
{
for(int i=0;i<ans.size();i++)
{
ans[i]=C(A.size(),i)*C(B.size(),i)%mod*jc[i]%mod;
}
return ans;
}
if(A.empty()||B.empty())
{
ans[0]=1;
return ans;
}
for(int j=0;j<A.size();j++)
{
a[(A[j]>>id)&1].push_back(A[j]);
}
for(int j=0;j<B.size();j++)
{
b[(B[j]>>id)&1].push_back(B[j]);
}
if(((k>>id)&1)==1)
{
c[0]=calc(a[0],b[1],id-1);
c[1]=calc(a[1],b[0],id-1);
for(int i=0;i<c[0].size();i++)
{
for(int j=0;j<c[1].size();j++)
{
ans[i+j]+=(c[0][i]*c[1][j]%mod);
ans[i+j]%=mod;
}
}
}
else
{
c[0]=calc(a[0],b[0],id-1);
c[1]=calc(a[1],b[1],id-1);
for(int i=0;i<c[0].size();i++)
{
for(int j=0;j<c[1].size();j++)
{
for(int l=0;i+l<=a[0].size()&&j+l<=b[1].size();l++)
{
for(int m=0;i+m<=b[0].size()&&j+m<=a[1].size();m++)
{
ans[i+j+l+m]+=(c[0][i]*c[1][j]%mod*C(a[0].size()-i,l)%mod*C(b[0].size()-i,m)%mod*C(a[1].size()-j,m)%mod*C(b[1].size()-j,l)%mod*jc[l]%mod*jc[m]%mod);
ans[i+j+l+m]%=mod;
}
}
}
}
}
return ans;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
int n;
cin>>n>>k;
pre();
vector<long long>a(n),b(n),c;
for(int i=0;i<n;i++)
{
cin>>a[i];
}
for(int i=0;i<n;i++)
{
cin>>b[i];
}
c=calc(a,b,59);
for(int i=1;i<=n;i++)
{
cout<<(c[i]+mod)%mod<<"\n";
}
return 0;
}