题目地址:http://poj.org/problem?id=2992
解析:忽然感觉好坑,一直TLE,后来才发现不是思路问题,是输入输出的问题(坑啊)。(以下两种方法都可以)。
#include <iostream>
#include <cmath>
#include <string>
#include <cstring>
#include <algorithm>
#include <cstdio>
using namespace std;
typedef long long ll;
#define INF 0xfffffff
#define MAX(a,b) a>b?a:b
#define MIN(a,b) a>b?b:a
#define M 1000
short int flag[M];
int prime[500];//当M比较大的时候(大于10e5)素数大概就是范围的1/10
int q=0;//素数的下标
void sieve_prime() //筛法求素数
{
memset(flag,0,sizeof(flag));
int i;
for(i=2;i*i<M;i++) { //边筛边存
if(flag[i]) continue;
prime[q++]=i;
for(int j=i*i;j<M;j+=i)
flag[j]=1;
}
for(i;i<M;i++) //存另一部分素数
if(!flag[i]) prime[q++]=i;
}
int a[M],b[M];
int resolve_factorial_0(int n)
{
int ans,temp;
for(int i=0;n>=prime[i];i++)
{
temp=prime[i];
ans=0;
while(temp<=n) ans+=n/temp,temp*=prime[i];
a[prime[i]]+=ans;
}
}
int resolve_factorial_1(int n)
{
int ans,temp;
for(int i=0;n>=prime[i];i++)
{
temp=prime[i];
ans=0;
while(temp<=n) ans+=n/temp,temp*=prime[i];
b[prime[i]]+=ans;
}
}
void solve(int n)
{
ll ans=1;
for(int i=0;prime[i]<=n&&a[prime[i]];i++)
ans*=(a[prime[i]]-b[prime[i]]+1);
printf("%I64d\n",ans); //最好用printf。
//cout<<ans<<endl;
}
int main()
{
int i,j,k,t;
int m,n;
ll ans;
sieve_prime();
while(scanf("%d%d",&n,&k)!=-1) //最好用scanf,
{
memset(a,0,sizeof(a));
memset(b,0,sizeof(b));
resolve_factorial_0(n);//将n!进行分解。
resolve_factorial_1(k);
resolve_factorial_1(n-k);
solve(n);
}
return 0;
}
另一种方法:
#include <iostream>
#include <cmath>
#include <string>
#include <cstring>
#include <algorithm>
#include <cstdio>
using namespace std;
typedef long long ll;
#define INF 0xfffffff
#define MAX(a,b) a>b?a:b
#define MIN(a,b) a>b?b:a
#define M 445
short int flag[M];
int prime[500];//当M比较大的时候(大于10e5)素数大概就是范围的1/10
int q=0;//素数的下标
void sieve_prime() //筛法求素数
{
memset(flag,0,sizeof(flag));
int i;
for(i=2;i*i<M;i++) { //边筛边存
if(flag[i]) continue;
prime[q++]=i;
for(int j=i*i;j<M;j+=i)
flag[j]=1;
}
for(i;i<M;i++) //存另一部分素数
if(!flag[i]) prime[q++]=i;
}
ll a[432][90];
ll re[432][432]; //预先存储在数组里面。
void init()
{
memset(a,0,sizeof(a));
ll ans,temp;
for(int i=0;i<q;i++)
for(int j=2;j<=431;j++)
a[j][i]+=j/prime[i]+a[j/prime[i]][i]; //j!里面含有prime【i】的个数
int i,j,k;
for(i=1;i<432;i++)
for(j=1;j<i;j++)
{
ans=1;
for(k=0;prime[k]<=i&&a[i][k];k++)
{
temp=a[i][k]-a[j][k]-a[i-j][k];
if(temp) ans*=(temp+1);
}
re[i][j]=ans;
}
}
int main()
{
int i,j,k,t;
int m,n;
sieve_prime();
init();
while(scanf("%d%d",&n,&k)!=-1)
{
if(k==0||k==n) printf("1\n");
else printf("%I64d\n",re[n][k]);
}
return 0;
}