题意:给两个集合,找出这两个集合中gcd为某个值的对数
思路:
b和d分别除以k之后的区间里面,只需要求gcd(x, y) = 1就可以了,这样子求出的数的对数不变。
这道题目还要求1-3 和 3-1 这种情况算成一种,因此只需要限制x
只需要枚举x,然后确定另一个区间里面有多少个y就可以了。因此问题转化成为区间(1, d)里面与x互素的数的个数
先求出x的所有质因数,因此(1,d)区间里面是x的质因数倍数的数都不会与x互素,因此,只需要求出这些数的个数,减掉就可以了。
如果w是x的素因子,则(1,d)中是w倍数的数共有d/w个。
#include
#include
#include
using namespace std;
typedef long long ll;
const int MAXN=1e5+5;
int prime[MAXN][10];
int cnt[MAXN];
void sieve(int n)
{
for(int i=2;i<=n;i++)
{
if(cnt[i]!=0) continue;
prime[i][0]=i;
cnt[i]=1;
for(int j=2;j*i<=n;j++)
prime[i*j][cnt[i*j]++]=i;
}
}
ll solve(int m,int n,int pos)
{
ll res=0;
for(int i=1;i<(1<>=1) num+=j&1;
int lcm=1;
for(int j=0;j>j&1)
{
lcm=lcm/__gcd(lcm,prime[pos][j])*prime[pos][j];
if(lcm>n) break;
}
}
if(num%2==0) res-=(ll)(n/lcm);
else res+=(ll)(n/lcm);
}
return res;
}
int main()
{
sieve(100005);
int t;
scanf("%d",&t);
int casi=1;
while(t--)
{
int a,b,c,d,e;
scanf("%d%d%d%d%d",&a,&b,&c,&d,&e);
if(e==0)
{
printf("Case %d: %lld\n",casi++,0);
continue;
}
b/=e;d/=e;
if(b>d) swap(b,d);
ll ans=0;
for(int i=a;i<=b;i++)
{
ans+=(ll)d-(solve(cnt[i],d,i))-((ll)(i-1)-(solve(cnt[i],i-1,i)));
}
printf("Case %d: %lld\n",casi++,ans);
}
return 0;
}