题意:求一个区间[1,m]内与i的互质的数的个数。这里1<=i<=n,
思路:对i分解质因子然后容斥
代码:
#include <cstdio> #include <cstring> #include <algorithm> typedef long long LL; const int maxn = 100010; LL ans; int n,m; int fac[maxn]; int prime[maxn]; int facCnt; void getPrime() { bool flag[maxn]; memset(flag,false,sizeof(flag)); prime[0] = 0; for(int i = 2; i < maxn; i++) { if(flag[i] == false) prime[++prime[0]] = i; for(int j = 1; j <= prime[0]&&i*prime[j]<maxn; j++) { flag[i*prime[j]] = true; if(i % prime[j] == 0) break; } } } void getFac(int num) { int tmp = num; facCnt = 0; for(int i = 1; i <= prime[0] && prime[i]*prime[i] <= tmp; i++) { if(tmp % prime[i] == 0) { fac[facCnt++] = prime[i]; while(tmp%prime[i] == 0) tmp /= prime[i]; } if(tmp == 1) break; } if(tmp > 1) fac[facCnt++] = tmp; } LL solve(int m) { int que[110]; int l = 0; que[l++] = 1; for(int i = 0; i < facCnt; i++) { int k = l; for(int j = 0; j < k; j++) que[l++] = fac[i]*que[j]*(-1); } LL anw = 0; for(int i = 0; i < l; i++) anw += m/que[i]; return anw; } int main() { int test;getPrime(); scanf("%d",&test); for(int item = 1; item <= test; item++) { scanf("%d %d",&n,&m); if(n > m) std::swap(n,m); ans = 0; for(int i = 1; i <= n; i++) { getFac(i); ans += solve(m); } printf("%I64d\n",ans); } return 0; }
时间: 2024-10-08 10:14:24