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 M个整数,依次对应zhu的每个咸数(1≤咸数≤2∗105). OUTPUT 对于每组数据,输出答案.
SAMPLE INPUT 2 10 1
3 10 1 1
SAMPLE OUTPUT
3 10
很明显是个容斥,可惜具体不会。。 然后画个图,找规律,
这个题是很经典的容斥啊,不过我以前做的是容斥是统计所有格子的,这个容斥需要统计奇数个的数字个数,两个相同的数异或为0
所以我就要对之前的容斥进行修改,比如A BC,我以前是 A+B+C-AC-AB-BC+ABC,现在我需要做的是A+B+C-2AC-2AB-2BC+4ABC,和我当前id有关,2的几次幂,然后就可以过了 就是把两个合并的都删掉了 接着 中间的小部分 3-2-2-2+4=1。
#include <bits/stdc++.h>
using namespace std;
long long ans,a[30];
int n,m;
long long gcd(long long a,long long b)
{
return b==0?a:gcd(b,a%b);
}
void dfs(int cur,long long lcm,int id)
{
lcm=a[cur]/gcd(a[cur],lcm)*lcm;
if(id&1)
ans+=n/lcm*(1<<(id-1));
else ans-=n/lcm*(1<<(id-1));
if(lcm<=n)
for(int i=cur+1;i<m;i++)
dfs(i,lcm,id+1);
}
int main()
{
int t;
cin>>t;
while(t--)
{
ans=0;
cin>>n>>m;
for(int i=0;i<m;i++)
cin>>a[i];
for(int i=0;i<m;i++)
dfs(i,a[i],1);
cout<<ans<<endl;
}
}