ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

3504. 【NOIP2013模拟11.4B组】运算符(calc)

2019-08-17 20:06:59  阅读:333  来源: 互联网

标签:NOIP2013 11.4 ll 运算符 ans return include bz define


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

标签:NOIP2013,11.4,ll,运算符,ans,return,include,bz,define
来源: https://blog.csdn.net/zsjzliziyang/article/details/99697121

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有