题目
题目描述
给出n个数a1,a2……an,求区间[L,R]中有多少个整数不能被其中任何一个数整除。
输入
第一行三个正整数,n,L,R。
第二行n个正整数a1,a2……an
输出
一个数,即区间[L,R]中有多少个整数不能被其中任何一个数整除。
样例输入
2 1 1000
10 15
样例输出
867
数据范围
对于30%的数据,1<=n<=10,1<=L,R<=1000
对于100%的数据,1<=n<=18,1<=L,R<=10^9
题目大意
这道题主要是说,在 L L L~ R R R的区间内有多少个数与输入的 a i a_i ai都互质
思路
这道题我的思路使用容斥来做,本来能AC的,模拟赛的时候由于某种原因导致我的时间不够导致 TLE 30。
我们可以先算出能被
a
i
a_i
ai整除的个数,再用再用总数减掉它们。
那问题来了,要求的是
L
L
L~
R
R
R区间内的个数,
L
L
L也不一定从1开始,那这怎么处理呢?我们可以考虑用1 ~
R
R
R区间个数减去1 ~
L
L
L-
1
1
1 区间个数即为
L
L
L~
R
R
R区间的个数。
如图,上图三个圈的总数为:
三个圈的和(即整体)- 两个圈的交集 + 三个圈的交集
由此,我们可以得到规律:
总数 = 整体 - 两个的交集 + 三个的交集 - 四个的交集 + 五个的交集……
Code
#include<bits/stdc++.h>
#define ll long long
using namespace std;
ll n,l,r,ri,a[20],ans,ans1,tot;
ll f[100005][20],aa[20];
int cnt[20],bz[20];
int gcd(int m,int n)
{
if(m<n) swap(m,n);
int r;
while(n!=0)
{
r=m%n;
m=n;
n=r;
}
return m;
}
ll getans(ll t)
{
ll s=0;
for(int i=1;i<=n;i++)
{
ll js=0;
for(int j=1;j<=cnt[i];j++)
js+=t/(f[j][i]);
if(i%2==0) s+=js;
else s-=js;
}
return s;
}
void choose(int sh,int x,int k)
{
if(k>x)
{
ll total=1;
for(int i=1;i<=x;i++)
{
int gc=gcd(total,a[aa[i]]);
total*=a[aa[i]]/gc;
if(total>r) break;
}
if(total<=r)
{
++cnt[x];
f[cnt[x]][x]=total;
}
}
else
{
for(int i=sh;i<=n;i++)
if(!bz[i])
{
aa[k]=i;
bz[i]=1;
choose(i+1,x,k+1);
bz[i]=0;
}
}
}
int main()
{
scanf("%lld%lld%lld",&n,&l,&r);
for(int i=1;i<=n;i++)
scanf("%lld",&a[i]);
ri=l-1;
ans=r;
ans1=ri;
for(int i=1;i<=n;i++)
{
memset(bz,0,sizeof(bz));
memset(aa,0,sizeof(aa));
choose(1,i,1);
}
ans1+=getans(ri);
ans+=getans(r);
printf("%lld",ans-ans1);
}