10.06 容斥练习T1

Description

众所周知zhu是一个大厨,zhu一直有自己独特的咸鱼制作技巧.
tang是一个咸鱼供应商,他告诉zhu在他那里面有N条咸鱼(标号从1到N)可以被用来制作.
每条咸鱼都有一个咸鱼值Ki,初始时所有Ki都是0.
zhu是一个特别的人,他有M个咸数(咸鱼数字), 对于每个咸数x,他都会让所有满足标号是x倍数的咸鱼的咸鱼值异或上1.
zhu现在想知道经过了这M个咸数的筛选之后,最终有多少条的咸鱼的咸鱼值是1?

Input

输入的第一行包含一个整数T(1≤T≤1000),表示有T组数据.
对于每组数据:
输入第一行只有两个整数N(1≤N≤10^9),M(1≤M≤15).
接下来一行有M个整数,依次对应zhu的每个咸数(1≤咸数≤2∗10^5).

Output

对于每组数据,输出答案.

Sample Input

2
10 1
3
10 1
1

Sample Output

3
10
 
 
 
 
此题一看就是个容斥然后上模板。。。。。。。然后你就WA了
为什么
1.因为这个东西直接容斥的话你会发现你是求的是全部数中可以整除那些值(或的关系)的全部个数
那么这个实际上是求的被运算奇数次的,画个图实际上我们就知道直接加减明显是错误的
 
2.我们除n的数字不是这些元素简单的积,而是他们的 lcm ,这个好理解但是很容易忽略
 
3.最后做系数的时候要大胆猜测,同时注意我们要先向下取整再乘上系数,这样才是完全正确的
 
4.记得开long long
 code:
 1 #include<iostream>
 2 #include<cstdio>
 3 using namespace std;
 4 long long x[20];
 5 long long gcd(long long a,long long b){
 6     if(a>b)swap(a,b);
 7     while(a=a%b)swap(a,b);
 8     return b;
 9 }
10 long long lcm(long long a,long long b){
11     return a*b/gcd(a,b);
12 }
13 int main(){
14     long long T;cin>>T;
15     while(T--){
16         long long n,m;
17         cin>>n>>m;
18         for(long long i=1;i<=m;i++)cin>>x[i];
19         long long all=(1<<m)-1;
20         long long ans=0;
21         for(long long i=1;i<=all;i++){
22             long long now=0;
23             long long mul=1;
24             for(long long j=1;j<=m;j++){
25                 if(i>>(j-1)&1)now++,mul=lcm(mul,x[j]);
26             }
27         //    cout<<"mul->"<<mul<<'\n';
28             if(now&1){
29                 ans+=n/mul*(1<<now-1);
30             }
31             else ans-=n/mul*(1<<now-1);
32         }
33         cout<<ans<<'\n';
34     }
35     return 0;
36 }

over

posted @ 2018-10-06 15:47  saionjisekai  阅读(33)  评论(0编辑  收藏  举报