1339: WitchMirror [数论]
时间限制: 1 Sec 内存限制: 128 MB题目描述
王炸的队友地雷(你可以叫他雷雷)要考科一了,但地雷总是不太自信,因为他看的题太少了。
王炸为了帮他,就拿出来了一面魔镜,这个魔镜可以告诉雷雷他还不会的题有多少。但是魔镜自诩是hpu毕业的高材生,并不想直接了当的告诉地雷,他通过以下这种方式让地雷自己计算出来:
魔镜给地雷m个数字(a1、a2 …… am)和一个整数n,魔镜定义:如果有一个数,是这m个数字里面任意一个数的倍数,那么这个数称为LuckyNumber。而雷雷会的题数为[1,n]闭区间内LuckyNumber的数量。
那么请你帮地雷计算一下他会的题目数。
输入
有多组数据,每组数据第一行给出两个字母n、m,含义如题意所示。
数据第二行给出m个整数:a1、a2 …… am。
(1≤ n、a1、a2 …… am ≤ 1e9,1 ≤ m ≤ 15 )
输出
输出一个整数,表示地雷会的题目数。
样例输入
10 2
5 7
100 1
1
样例输出
3
100
思路:容斥裸题,注意 p[ i ] == n 的情况和 LL。
sum = 被1个数整除的个数-被2个数整除的个数+被3个数整除的个数-.... (奇加偶减);
#include<cstdio>
#include<cstring>
typedef long long LL;
LL p[1010],k;
LL gcd(LL a,LL b)
{
return b?gcd(b,a%b):a;
}
LL lcm(LL a,LL b)
{
return a/gcd(a,b)*b;
}
LL nop(LL m)
{
LL res,sum=0,use;
for(LL i=1;i<1<<k;i++)
{
res=1,use=0;
for(LL j=0;j<k;j++)
{
if(i & (1<<j))
{
use++;
res=lcm(res,p[j]);
}
}
if(use & 1) sum+=m/res;
else sum-=m/res;
}
return sum;
}
int main()
{
LL n;
while(scanf("%lld%lld",&n,&k)!=EOF)
{
for(LL i=0;i<k;i++)
{
scanf("%lld",&p[i]);
if(p[i]>n)
i--,k--;
}
printf("%lld\n",nop(n));
}
return 0;
}