题目出自北方大学acm多校训练赛第四场
V1(原题)
题目大意
定义函数 f(n,0)=1, f(n,m)=∑d∣nf(d,m−1)⋅f(dn,m−1)
给定 n,m,求 f(n,m)mod10007
多组数据,T≤10, n≤109, m≤50
(这题我想了十几分钟没想出来,然后jasonvictoryan走过来,想了10秒钟,想出了V2解法。。。)
题解
据说 n 的约数很少,直接暴力就。。。过了???
V2
题目大意
数据范围改成 T≤103, n≤1018, m≤105
(这个模数感觉好容易误判。。。改成 109+7 吧。。。)
题解
长成 f(i)=∑d∣nf(d)∗f(di) 这个样子的,多半是积性函数。
进而发现,同一层的 f 是积性函数。(同一层是指 m 相同)
所以只用求出 f(pici,m) 就行了,其中 n=Πpici
进而发现,这个东西跟 pi 没有关系,只跟 ci 有关。
这里可能存在什么公式可以直接求出来,不过由于 ci<64,所以预处理也行。
然后大整数分解质因数用 pollard_rho。
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
| #include<cmath> #include<cstdio> #define fo(i,a,b) for(int i=a;i<=b;i++) using namespace std;
const int mo=10007;
int n,m,p0,p[100][2];
int T,f[100][100]; int main() { fo(i,0,30) f[i][0]=1; fo(j,1,50) fo(i,0,30) fo(k,0,i) f[i][j]=(f[i][j]+f[k][j-1]*f[i-k][j-1])%mo; scanf("%d",&T); while (T--) { scanf("%d %d",&n,&m); int sqrtn=sqrt(n); p0=0; fo(i,2,sqrtn) if (n%i==0) { p[++p0][0]=i; p[p0][1]=0; for(; n%i==0; n/=i) p[p0][1]++; } if (n>1) p[++p0][0]=n, p[p0][1]=1; int ans=1; fo(i,1,p0) ans=ans*f[p[i][1]][m]%mo; printf("%d\n",ans); } }
|