牛客练习赛43-F(简单容斥)

题目链接:https://ac.nowcoder.com/acm/contest/548/F

题意:简化题意之后就是求[1,n]中不能被[2,m]中的数整除的数的个数。

思路:简单容斥题,求[1,n]中不能被[2,m]中的数整除的数的个数,可以通过求能够被整除的数。

   首先,[2,m]中的合数肯定能由[2,m]中的素数的乘积来表示,所以我们仅需要考虑[1,n]中能由[2,m]中的素数整除的数的个数即可,记为sum。

   然后,我们知道[1,n]中能够被x整除的数的个数为n/x(向下整除)。

   then,如果按上一步计算的话,会出现重复计算的问题,这个时候就用到了容斥原理,若[2,m]有p个素数,分别为cnt[1]..cnt[p],那么这p个素数可以有1<<p-1个组合,记该组合中所有素数乘积为tmp,素数个数为num,则能被tmp整除的数有(n/tmp)个,若num为奇数,则sum加上(n/tmp),若为偶数,则sum减上(n/tmp),这样就解决了问题。还有本题要注意的一个小细节是若k==0,直接输出QAQ即可。

AC代码:

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 typedef long long LL;
 4 
 5 int T,m,cnt[10]={0,2,3,5,7,11,13,17,19};
 6 int M[25]={0,0,1,2,2,3,3,4,4,4,4,5,5,6,6,6,6,7,7,8,8};
 7 LL k,q,n,sum;
 8 
 9 int main(){
10     scanf("%d",&T);
11     while(T--){
12         scanf("%lld%lld%lld%d",&k,&q,&n,&m);
13         int p=M[m];
14         sum=0;
15         for(int i=1;i<(1<<p);++i){
16             int num=0;
17             LL tmp=1;
18             for(int j=1;j<=p;++j)
19                 if((1<<(j-1))&i){
20                     ++num;
21                     tmp*=cnt[j];
22                 }
23             if(num&1)
24                 sum+=n/tmp;
25             else
26                 sum-=n/tmp;
27         }
28         sum=(n-sum)+k-1;
29         if(sum>n) sum=n;
30         if(k&&sum>=q) printf("Yes\n");
31         else printf("QAQ\n");
32     }
33     return 0;
34 }

猜你喜欢

转载自www.cnblogs.com/FrankChen831X/p/10664483.html