您的位置:首页 > 其它

ZOJ 2836 Number Puzzle(容斥原理)

2016-04-03 14:52 281 查看
给出1到10的十个数字,要求输出不大于m的数字能被其中任意一个整除的数字有多少个

简单的熔池原理,我们用二进制枚举每个数字的选择情况,然后当选择的数字为奇数时将总数加上m/gcd 偶数时减去

#include <iostream>
#include <cstdio>
#include <set>
#include <string>
#include <string.h>
#include <cstring>
#include <vector>
#include <map>
#include <queue>
#include <stack>
#include <cctype>
#include <algorithm>
#include <sstream>
#include<cstdlib>
#define mt(a) memset(a,0,sizeof a)
#define fl(a,b,c) fill(a,b,c)
#define pii pair<int,int>
#define INF 1000000000+7
#define MAXN 100005
#define mody 1000000007
#define iin(x) scanf("%d",&x)
#define complete_unique(x) x.erase(unique(x.begin(),x.end()),x.end())
using namespace std;
typedef long long ll;
#define sp system("pause")

ll gcd(ll x,ll y)
{
return (x == 0 ? y : gcd(y % x,x));
}

ll lcm(ll x,ll y)
{
return x / gcd(x,y) * y;
}

int main()
{
ll n,m;
while(cin >> n >> m)
{
map<ll,ll>mp;
for(int i = 0;i < n;i++)
{
ll h;
cin >> h;
mp[h]++;

}

if(mp[1] == 1)
{
cout << m << endl;
continue;
}

ll ans=0;
for(int s=0;s<(1<<10);s++)
{
int flag=1;
int cot=0;
ll  lc=1;
for(int i=0;i<10;i++)
{
if(s&(1<<i)&&!mp[i])
{
flag=0;break;
}
if(s&(1<<i)&&mp[i])lc=lcm(lc,i),cot++;
}
if(!flag)continue;
if(cot&1)ans+=(m/lc);
else if(cot!=0) ans-=(m/lc);
}
cout <<ans << endl;
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: