URAL 1091

题意:
从 s 个数里挑出 k 个, 这个 k 个数的共因子大于 1 一共有多少种方法

思路:
很裸的容斥,首先只选择小于k的质因子i,个数显然是C(s/i,k),由k>=2知道,i最多枚举到s/2,所以预处理组合数,跑一次容斥即可

#include<iostream>
#include<cstdio>
#include<cstring>

using namespace std;
typedef long long ll;
int c[30][30],ans,cnt;
int k,s;
int a[]={ 0,2,3,5,7,11,13,17,19,23};
void dfs(int pos,int sum,int li)
{
    sum=a[pos]*sum;
    if(s/sum<k)return;
    if(li&1)
        ans+=(c[s/sum][k]);
    else
        ans-=(c[s/sum][k]);
    if(ans>10000)return;
    for(int i=pos+1;i<=cnt;++i)
        dfs(i,sum,li+1);
}
int main()
{
   c[0][0]=1;
   for(int i=1;i<=26;++i)
   {
      c[i][0]=c[i][i]=1;
      for(int j=1;j<i;++j)	
         c[i][j]=c[i-1][j-1]+c[i-1][j]; 
   } 
   scanf("%d%d",&k,&s);
   for(int i=9;i>=1;--i)
   {
       if(s/a[i]>=k){ 
            cnt=i;
            break;
       }
   } 
   for(int i=1;i<=cnt;++i)
       dfs(i,1,1);
   if(ans>10000)
       puts("10000");
   else 
       printf("%d\n",ans);
   return 0; 
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值