1138 - 震惊,99%+的中国人都会算错的问题
Time Limit:4s Memory Limit:128MByte
Submissions:310Solved:87
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≤109),M(1≤M≤15). 接下来一行有M个整数,依次对应zhu的每个咸数(1≤咸数≤2∗105
).
OUTPUT
对于每组数据,输出答案.
SAMPLE INPUT
2
10 1
3
10 1
1
SAMPLE OUTPUT
3
10
容斥原理,因为异或之后,值一直在1,0,之间变动
#include <iostream> #include <algorithm> #include <cstring> #include <cstdio> #include <vector> #include <queue> #include <cmath> #include <ctime> #include <map> #include <set> using namespace std; #define lowbit(x) (x&(-x)) #define max(x,y) (x>y?x:y) #define min(x,y) (x<y?x:y) #define MAX 100000000000000000 #define MOD 1000000007 #define pi acos(-1.0) #define ei exp(1) #define PI 3.141592653589793238462 #define INF 0x3f3f3f3f3f #define mem(a) (memset(a,0,sizeof(a))) typedef long long ll; ll n,t,m,a[20]; ll ans; ll gcd(ll x,ll y) { return y==0?x:gcd(y,x%y); } void dfs(ll cur,ll lcm,ll x) { lcm=a[cur]/gcd(a[cur],lcm)*lcm; if(x&1) ans+=n/lcm*(1<<(x-1)); else ans-=n/lcm*(1<<(x-1)); for(int i=cur+1;i<m;i++) dfs(i,lcm,x+1); } int main() { scanf("%lld",&t); while(t--) { ans=0; scanf("%lld%lld",&n,&m); for(int i=0;i<m;i++) scanf("%lld",&a[i]); for(int i=0;i<m;i++) dfs(i,a[i],1); printf("%lld\n",ans); } return 0; }