[数论][DP]JZOJ 5813 计数
分析
以下讨论的xi全部满足第一个限制条件
对于一组{x1,x2,..,x2m}<nm,显然:{n/x1,n/x2,..n/x2m}>nm
那么则两式相乘则为n2m,然后xi与n/xi显然一一对应,所以设上式为A和C,有A=C(方案数)
那么显然A+B(=nm的方案数)+C=σ(n)2m
所以A=(σ(n)2m+B)/2
那么就只需要求出=n2m的情况就行了,先分解质因数,设f[i][j]表示选了i位,和为j的方案数,DP即可
#include <istream> #include <cstdio> #include <memory.h> #include <cmath> using namespace std; typedef long long ll; const ll P=998244353; ll n,m,k,B; ll cnt,f[201][20001]; ll Power(ll x,ll y) { ll ans=1; while (y) { if (y&1) (ans*=x)%=P; (x*=x)%=P; y>>=1; } return ans; } void Solve(int l) { memset(f,0,sizeof f);f[0][0]=1; int ncnt=0; while (!(k%l)) k/=l,ncnt++; for (int i=1;i<=2*m;i++) for (int j=0;j<=ncnt*m;j++) for (int k=0;k<=min(j,ncnt);k++) (f[i][j]+=f[i-1][j-k])%=P; (B*=f[2*m][ncnt*m])%=P; } int main() { freopen("count.in","r",stdin); freopen("count.out","w",stdout); scanf("%lld%lld",&n,&m); k=n;B=1; for (int i=1;i<=sqrt(n);i++) if (!(n%i)) { cnt++; if (i*i<n) cnt++; if (i-1&&!(k%i)) Solve(i); } if (k>1) Solve(k); printf("%lld",(Power(cnt,2*m)+B)%P*Power(2,P-2)%P); fclose(stdin);fclose(stdout); }
在日渐沉没的世界里,我发现了你。