Description
鸡腿想到了一个很高(sha)明(bi)的运算符,那就是’!’,没错就是感叹号。他给了如下的定义:
1、n!k = n!(k-1) * (n-1)!k (n> 0 and k > 0)
2、n!k = 1 (n = 0)
3、n!k = n (k = 0)
现在鸡腿告诉你n和k你能告诉他n!k的不同约数个数有多少个吗?只要对1,000,000,009取模就可以了哦!
Input
一行,输入两个正整数n,k。
Output
一行,输出一个整数表示答案。
Sample Input
输入1:
3 1
输入2:
100 2
Sample Output
输出1:
4
输出2:
321266186
Data Constraint
对于30%的数据0 <n ≤ 10, 0 <k ≤ 10;
对于100%的数据0 <n ≤ 1000, 0 <k ≤ 100。
Solution
题意是定义n!k=(n-1)!k*n!(k-1),当k=0时n!k=n,当n=0时n!k=1,求n!k的约数的个数。
容易想到dp。
把整个过程看做一个矩阵。
设f[i][j][k]表示做到第i行第j列这个数的第k个质因子有多少个。
f[i][j][k]=f[i-1][j][k]+f[i][j-1][k]。
最后答案即为i=1~k(f[n][m][i]+1)的乘积。
但是我们发现如果n开大一些这样的算法就通不过了。
我们可以想因为只有(i,0)的点才会对答案有贡献,因此我们可以算出从(i,0)推到(n,m)的方案数,再用1~n的质因子直接累加即可。
那么(i,0)推到(n,m)的方案数是多少呢?
因为(i,0)只能由(i,1)推来所以我们就要计算(i,1)到(n,m)的方案。
同样抽象成一个二维平面,我们每次从(i,1)这个点出发,走到(n,m)的方案数,实际上就是C(n-i+m-1,n-i)。
至此我们可以求出每个质因子的倍数,此题得到解答。
第三种解法:
Code1
#include<cstdio>
#include<cstring>
#include<algorithm>
#define I int
#define F(i,a,b) for(I i=a;i<=b;i++)
#define Fd(i,a,b) for(I i=a;i>=b;i--)
#define ll long long
#define mem(a,b) memset(a,b,sizeof(a))
#define N 102
#define M 1000000009
using namespace std;
ll n,m,p[180],bz[1010],f[2][N][170],id[1010],o,ans=1;
I main(){
freopen("calc.in","r",stdin);
freopen("calc.out","w",stdout);
scanf("%lld%lld",&n,&m);
bz[1]=1;
F(i,2,n){
if(!bz[i]){
p[++p[0]]=i;
id[i]=p[0];
F(j,2,n/i) bz[j*i]=1;
}
}
F(i,1,n){
o=1-o;
F(k,1,p[0]) f[o][0][k]=0;
I x=i;
F(j,1,p[0]){
if(p[j]>x) break;
if(x%p[j]==0){
while(x%p[j]==0){
x/=p[j];
f[o][0][id[p[j]]]++;
f[o][0][id[p[j]]]%=M;
}
}
}
if(!bz[x]){
f[o][0][id[x]]++;
f[o][0][id[x]]%=M;
}
F(j,1,m){
F(k,1,p[0]) f[o][j][k]=0;
F(k,1,p[0]){
f[o][j][k]=(f[o][j][k]+f[1-o][j][k])%M;
f[o][j][k]=(f[o][j][k]+f[o][j-1][k])%M;
}
}
}
F(i,1,p[0]) ans=(ans*(f[o][m][i]+1)%M)%M;
printf("%lld\n",ans);
return 0;
}
Code2
#include<cstdio>
#include<cstring>
#include<algorithm>
#define I int
#define F(i,a,b) for(ll i=a;i<=b;i++)
#define Fd(i,a,b) for(ll i=a;i>=b;i--)
#define ll long long
#define mem(a,b) memset(a,b,sizeof(a))
#define N 1002
#define M 1000000009
using namespace std;
ll n,m,ans=1,p[200],bz[N],f[N*2],inv[N*2],c[200],t[200];
ll ksm(ll x,ll k){
if(k==1) return x;
ll s=ksm(x,k/2);s=(s*s)%M;
if(k&1) return (s*x)%M;
return s;
}
ll C(ll x,ll y){
return (((f[x]*inv[y])%M)*inv[x-y])%M;
}
I main(){
freopen("calc.in","r",stdin);
freopen("calc.out","w",stdout);
scanf("%lld%lld",&n,&m);
f[0]=1;
F(i,1,n+m) f[i]=(f[i-1]*i)%M;
inv[n+m]=ksm(f[n+m],M-2);
Fd(i,n+m-1,0) inv[i]=(inv[i+1]*(i+1))%M;
F(i,2,n){
if(!bz[i]) p[++p[0]]=i;
F(j,1,p[0]){
if(p[j]*i>n) break;
bz[p[j]*i]=1;
if(i%p[j]==0) break;
}
}
F(i,1,n){
ll x=i,st=C(n-i+m-1,m-1);
mem(c,0);
F(j,1,p[0]){
if(x%p[j]==0){
while(x%p[j]==0){
c[j]=(c[j]+st)%M;
x/=p[j];
}
if(x==1) break;
}
}
F(j,1,p[0]) t[j]=(t[j]+c[j])%M;
}
F(i,1,p[0]) ans=(ans*(t[i]+1))%M;
printf("%lld\n",ans);
return 0;
}
作者:zsjzliziyang
QQ:1634151125
转载及修改请注明
本文地址:https://blog.csdn.net/zsjzliziyang/article/details/99697121