HDU4135
Co-prime -- 欧拉函数+容斥
题意
给三个数,N,A,B,问区间[A,B]之间与N互质的数的个数,共有T组样例 (1<=T<=100, (1 <= A <= B <= 1015) and (1 <=N <= 109).)
分析
欧拉函数求的是1~n和n互质的个数,现在的问题求的是区间[A,B]与N互质的数的个数,根据数据范围显然不能直接求
互质不可以直接求,将其转化为不互质的,[1,n]与n不互质的数即为,n的质因子的倍数(由算数基本定理可知),故可以转化为求[1 , A-1]、[1 , B]和N不互质的个数,但求不互质的过程中存在重复(如,质因子2,3的的倍数都有6),需要容斥(奇加偶减),可将所有质因子看成一串二进制编码,算出即可
#include<bits/stdc++.h> #define ll long long using namespace std; const int maxn = 1e5+10; ll a[maxn], n, aa, b; int tot; void init(ll n) { tot=0; for(ll i=2;i*i<=n;i++) { if(n&&n%i==0) { while(n%i==0) { n/=i; } a[tot++]=i; } } if(n>1) a[tot++]=n; } ll solve(ll x) { ll sum=0; for(ll i=1;i<(1<<tot);i++) { ll val=1; int cnt=0; for(ll j=0; j<tot; j++) { if(i&(1<<j)) { val*=a[j]; cnt++; } } if(cnt&1) sum+=x/val; else sum-=x/val; } return x-sum; } int main() { int t; int Case=1; scanf("%d", &t); while(t--) { scanf("%lld%lld%lld", &aa, &b, &n); init(n); printf("Case #%d: %lld\n", Case++, solve(b)-solve(aa-1)); } return 0; }
要么优秀要么生锈