您的位置:首页 > 其它

HDU 1695 GCD (欧拉函数+容斥原理)

2015-11-12 14:01 337 查看

题目大意

求[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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  数论