您的位置:首页 > 其它

组合数问题

2016-11-30 14:13 211 查看

组合数问题

input:problem.in output:problem.out

Time Limits: 1000 ms Memory Limits: 521MB

Description



Input



Output



Sample Input

Input1:

1 2
3 3


Input2:

2 5
4 5
6 7


Sample Output

Output1:

1


Output2:

0
7


Hint

第一个数据样例说明



Data Constraint



解题思路

很明显的前缀和题目,

别告诉我你不知道这一点:

假设杨辉三角的首行为第0行,每行首个为第0个,则第i行第j个为Cij

杨辉三角对于k取模,则模为零的Cji 能被k整除

设pref[i][j] 表示满足k|Cqp(p∈[1,i],q∈[1,j],p>=q)的个数,

sum[i]=pref[i][i]

则对于给出的n,m,如果n<=m,则ans=s
否则ans=sum[m]+pref
[m]-pref[m][m]

很明显啊

不拿100对不起人了!

#include<cstring>
#include<cstdio>
using namespace std;
int yh[2001][2001],pr[2001][2001],sum[2001],n,m,t,k;

void init()
{
for(int i=0;i<=2000;i++)
{
yh[i][0]=yh[i][i]=1%k;
for(int j=1;j<i;j++)yh[i][j]=(yh[i-1][j-1]+yh[i-1][j])%k;
}
for(int i=1;i<=2000;i++)
{
for(int j=1;j<=2000;j++)
{
if(j<=i)if(!yh[i][j])pr[i][j]=1;
pr[i][j]+=pr[i][j-1]+pr[i-1][j]-pr[i-1][j-1];
}
sum[i]=pr[i][i];
}
}

int main()
{
freopen("problem.in","r",stdin);
freopen("problem.out","w",stdout);
scanf("%d %d\n",&t,&k);
init();
while(t--)
{
scanf("%d %d\n",&n,&m);
if(n<=m)printf("%d\n",sum
);else printf("%d\n",sum[m]+pr
[m]-pr[m][m]);
}
}


其实你也可以打质因数分解的:

#include<cstring>
#include<cstdio>
using namespace std;
int prime[2010],num[2010],p[2010],n,kk,t,m,sum[2010],pref[2010][2010],so[2010],nu[2010];
bool bz[2010],q;

void init()
{
for(int i=2;i<=2000;i++)/*素数线性筛法*/
{
if(!bz[i])
{
prime[++prime[0]]=i;
}
for(int j=1;j<=prime[0];j++)
{
if(i*prime[j]>2000)break;
bz[i*prime[j]]=1;
if(i%prime[j]==0)break;
}
}
int temp=kk;
for(int i=1;i<=prime[0];i++)/*将k分解质因数*/
{
if(temp==1)break;
if(temp%prime[i]==0)
{
while(temp%prime[i]==0)
{
temp/=prime[i];
p[prime[i]]++;
}
so[++so[0]]=prime[i];
}
}
for(int i=1;i<=2000;i++)
{
temp=i;
for(int j=1;j<=so[0];j++)
{
if(temp==1)break;
if(!bz[temp])
{
num[temp]++;
temp=1;
}
if(temp==1)break;
if(temp%so[j]==0)
{
while(temp%so[j]==0)temp/=so[j],num[so[j]]++;
}
}
for(int j=1;j<=so[0];j++)nu[so[j]]=-num[so[j]];
for(int j=1;j<=2000;j++)
{
if(i>=j)
{
temp=j;
for(int k=1;k<=so[0];k++)
{
if(temp==1)break;
if(!bz[temp])
{
nu[temp]--;
temp=1;
}
if(temp==1)break;
if(temp%so[k]==0)
{
while(temp%so[k]==0)temp/=so[k],nu[so[k]]--;
}
}
temp=i-j+1;
for(int k=1;k<=so[0];k++)
{
if(temp==1)break;
if(!bz[temp])
{
nu[temp]++;
temp=1;
}
if(temp==1)break;
if(temp%so[k]==0)
{
while(temp%so[k]==0)temp/=so[k],nu[so[k]]++;
}
}
q=1;
for(int k=1;k<=so[0];k++)
if(num[so[k]]+nu[so[k]]<p[so[k]])
{
q=0;break;
}
if(q)pref[i][j]=1;
}
pref[i][j]+=pref[i-1][j]+pref[i][j-1]-pref[i-1][j-1];
}
sum[i]=pref[i][i];
}
}

int main()
{
freopen("problem.in","r",stdin);
freopen("problem.out","w",stdout);
scanf("%d%d",&t,&kk);
init();
for(int i=1;i<=t;i++)
{
scanf("%d%d",&n,&m);
int ans;
if(n>m)
{
ans=sum[m]+pref
[m]-pref[m][m];
}else
{
ans=sum
;
}
printf("%d\n",ans);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: