卧薪尝胆,厚积薄发。
提高A组模拟 计算
Date: Thu Aug 16 07:36:50 CST 2018 In Category: NoCategory

Description:

给定 $n$ ,求合法的 $\{x_1,x_2,x_3,\dots,x_{2m}\}$ 组数,一组 $\{x\}$ 是合法的当且仅当
  • $\forall i\in[1,2m],\ x_i\in Z^+,\ x_i|n$
  • $\begin{align}\prod_{i=1}^{2m}x_i\le n^m\end{align}$
$1\le n \le 10^9$ $m \le 100$

Solution:

若一组 $\{x_1,x_2,x_3,\dots,x_{2m}\}< n^m$ ,那么 $\{\frac n{x_1},\frac n{x_2},\frac n{x_3},\dots,\frac n{x_{2m}}\}>n^m$ ,设小于 $n^m$ 的组数记为 $S_1$ ,等于 $n^m$ 的组数记为 $S_2$ ,大于的记为 $S_3$ ,那么由于 $S_1$ 和 $S_3$ 中的方案一一对应,所以 $S_1=S_3$ ,由于 $S_1+S_2+S_3=\sigma_0(n)^{2m}$ ,所以只要计算出 $S_2$ 即可,可以把每一个质因数分别考虑, $f[i][j]$ 表示 $i$ 个人指数和为 $j$ ,转移时直接枚举最后一个数的指数转移。

Code:


nclude<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<cstring>
using namespace std;
int n,m;
#define MAXM 101
typedef long long ll;
ll f[MAXM << 1][31 * MAXM];
int sigma0 = 0;
int fac[MAXM],cnt[MAXM],tot = 0;
#define MOD 998244353
ll power(ll a,int b)
{
ll res = 1;
while(b > 0)
{
if(b & 1)res = res * a % MOD;
a = a * a % MOD;
b = b >> 1;
}
return res;
}
int main()
{
freopen("count.in","r",stdin);
freopen("count.out","w",stdout);
cin >> n >> m;
int s = n;
for(int i = 1;i * i <= n;++i)
{
if(n % i == 0)
{
++sigma0;
if(i * i != n)
{
++sigma0;
}
}
}
for(int i = 2;i * i <= n;++i)
{
if(s % i == 0)
{
fac[++tot] = i;
while(s % i == 0){s /= i;++cnt[tot];}
}
}
if(s != 1)fac[++tot] = s,cnt[tot] = 1;
ll S2 = 1;
for(int k = 1;k <= tot;++k)
{
memset(f,0,sizeof(f));
f[0][0] = 1;
for(int i = 1;i <= 2 * m;++i)
{
for(int j = 0;j <= cnt[k] * m;++j)
{
for(int l = 0;l <= cnt[k];++l)
{
if(j - l >= 0)f[i][j] = (f[i][j] + f[i - 1][j - l]) % MOD;
}
}
}
S2 = (S2 * f[2 * m][cnt[k] * m]) % MOD;
}
cout << (power(sigma0,2 * m) + S2) % MOD * power(2,MOD - 2) % MOD << endl;
fclose(stdin);
fclose(stdout);
return 0;
}
Copyright © 2020 wjh15101051
ღゝ◡╹)ノ♡