题目大意
- 求[1,b]的x与[1,d]的y的二元组数,需满足gcd(x , y) == k,且二元组无序,即(1,2)和(2,1)视为同一个二元组
分析
- 可转化为:令b/=k , d/=k。求[1,b]和[1,d]互质的二元组数量。
假设d>b,枚举[1,d]中的每个数i。
当i <= b 时,[1,b]中与i互质的数的为i的欧拉函数 当i > b 时,求[1,b]中与i互质的数的个数就要用到容斥原理
容斥原理: 区间中与i不互质的个数 = (区间中i的每个质因数的倍数个数)-(区间中i的每两个质因数乘积的倍数)+(区间中i的每3个质因数的乘积的倍数个数)-(区间中i的每4个质因数的乘积)+…
- 此题的大致思路:
- 初始化得到[1,maxn]中每个数i素因子个数num[i],i个所以素因子p[i][j]。以及[1,i]的欧拉函数之后pih[i]
- 令b <= d。ans = phi[b],然后从b+1处开始遍历,对于每个数i,用容斥原理求[1,b]中与它不互质的数的个数。
int DFS(int k , int b , int cur) //[1,b]中与cur不互质的数的个数
{
int rel = 0;
for(int i = k; i < num[cur]; i++) {
rel += b / p[cur][i] - DFS(i + 1 , b / p[cur][i] , cur);
}
return rel;
}
代码
#include <iostream>
using namespace std;
const int maxn = 100005;
typedef long long ll;
int num[maxn] = {0}; //num[i]表示i的素因子个数
int p[maxn][20]; //p[i]存放i的素因子
ll phi[maxn] = {0};
void phi_table () //打表
{
phi[1] = 1;
for(int i = 2; i < maxn; i++)
{
if(phi[i]) {phi[i] += phi[i-1]; continue;} //不是素数
for(int j = i; j < maxn; j += i)
{
if(!phi[j]) phi[j] = j;
phi[j] = phi[j] * (i-1) / i;
p[j][num[j]++]=i;
}
phi[i] += phi[i-1];
}
}
int DFS(int k , int b , int cur) //[1,b]中与cur不互质的数的个数
{
int rel = 0;
for(int i = k; i < num[cur]; i++) {
rel += b / p[cur][i] - DFS(i + 1 , b / p[cur][i] , cur);
}
return rel;
}
int main()
{
phi_table();
int t , caseno = 1;
cin >> t;
while(t--)
{
int a , b , c , d , k;
cin >> a >> b >> c >> d >> k;
if(k == 0) {
cout << "Case " << caseno++ << ": " << 0 << endl;
continue;
}
if(b > d) swap(b , d);
b /= k , d /= k;
ll ans = phi[b];
for(int i = b + 1; i <= d; i++) {
ans += b - DFS(0 , b , i);
}
cout << "Case " << caseno++ << ": " << ans << endl;
}
return 0;
}