题目:http://acm.hdu.edu.cn/showproblem.php?pid=1695
题意:给定五个数,其中有和,求满足条件的有序对的个数。题目中
明确说在所有的输入中。
分析:问题可以转化为和时,的有序对的个数。那么先比较和的
大小,相同的部分可以用欧拉函数的累加计算,没有公共的部分用容斥计算即可。
当然,在用容斥计算时,对于每一个数要进行dfs,这样必然会对每一个数进行素因子分解,实际上我们可以对
每一个数进行线性筛,从而计算出它的所有素因子以及每一个素因子出现的次数,这样预处理时间快很多。
代码:
#include <iostream> #include <string.h> #include <algorithm> #include <stdio.h> using namespace std; const int N = 100005; typedef long long LL; LL phi[N]; int num[N]; int p[N][15]; void Init() { memset(num,0,sizeof(num)); memset(phi,0,sizeof(phi)); phi[1] = 1; for(int i=2;i<N;i++) { if(!phi[i]) { for(int j=i;j<N;j+=i) { if(!phi[j]) phi[j] = j; phi[j] = phi[j] - phi[j] / i; p[j][num[j]++] = i; } } phi[i] += phi[i-1]; } } LL dfs(int x,int r,int n) { LL ans = 0; for(int i=x;i<num[n];i++) ans += r / p[n][i] - dfs(i+1,r/p[n][i],n); return ans; } int main() { Init(); int tt = 1; int T; scanf("%d",&T); while(T--) { int a,b,k; scanf("%d%d%d%d%d",&a,&a,&b,&b,&k); if(a > b) swap(a,b); if(k == 0) { printf("Case %d: 0\n",tt++); continue; } a /= k; b /= k; LL ans = phi[a]; for(int i=a+1;i<=b;i++) ans += a - dfs(0,a,i); printf("Case %d: %I64d\n",tt++,ans); } return 0; }