记录编号 |
443775 |
评测结果 |
AAAAAAAAAAAAAAAAAAAA |
题目名称 |
[NOIP 2016]组合数问题 |
最终得分 |
100 |
用户昵称 |
nonamenotitle |
是否通过 |
通过 |
代码语言 |
C++ |
运行时间 |
0.835 s |
提交时间 |
2017-09-01 10:17:49 |
内存使用 |
46.32 MiB |
显示代码纯文本
#include <bits/stdc++.h>
using namespace std;
const int maxn=2000+5;
int dp[maxn][maxn];
int t,k,n,m;
int hav[maxn][maxn],sum[maxn][maxn];
map<int ,int > divk;
int havk(int sol,int x){
int ret=0;
while(x%sol==0) x/=sol,ret++;
return ret;
}
map<int ,int > divisor(int x){
map<int,int > ret;ret.clear();
for(int i=2;i*i<=x;i++){
while(x%i==0) x/=i,ret[i]++;
}
if(x!=1) ret[x]++;
return ret;
}
void proce(){
for(map<int ,int >::iterator ite=divk.begin();ite!=divk.end();++ite){
int u=ite->first;
for(int i=1;i<maxn;i++){
hav[u][i]=havk(u,i);
}
for(int i=1;i<maxn;i++) sum[u][i]=sum[u][i-1]+hav[u][i];
}
}
int main()
{
freopen("problem.in","r",stdin);
freopen("problem.out","w",stdout);
scanf("%d%d",&t,&k);
divk=divisor(k);
/*for(map<int ,int >::iterator ite=divk.begin();ite!=divk.end();ite++){
printf("%d: %d\n",ite->first,ite->second);
}puts("");*/
proce();
for(int i=1;i<maxn;++i){
for(int j=1;j<=i;++j){
bool can=true;
for(map<int ,int >::iterator ite=divk.begin();ite!=divk.end();++ite){
int u=ite->first;
if(sum[u][i]-(sum[u][j]+sum[u][i-j])<ite->second) {can=false;break;}
}
dp[i][j]=can?1:0;
}
}
/*for(int i=0;i<10;i++){
for(int j=0;j<10;j++){
printf("dp[%d][%d]=%d\n",i,j,dp[i][j]);
}puts("");
}*/
for(int i=1;i<maxn;++i){
for(int j=1;j<=i;++j) dp[i][j]+=dp[i][j-1];
for(int j=i+1;j<maxn;++j) dp[i][j]=dp[i][j-1];
}
for(int i=1;i<maxn;++i){
for(int j=0;j<maxn;j++){
dp[i][j]=dp[i-1][j]+dp[i][j];
}
}
/*for(int i=0;i<10;i++){
for(int j=0;j<10;j++){
printf("dp[%d][%d]=%d\n",i,j,dp[i][j]);
}puts("");
}*/
for(int z=0;z<t;++z){
scanf("%d%d",&n,&m);
printf("%d\n",dp[n][min(n,m)]);
}
return 0;
}