FJUT3565 最大公约数之和(容斥)题解
Posted kirinsb
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了FJUT3565 最大公约数之和(容斥)题解相关的知识,希望对你有一定的参考价值。
题意:给n,m,求出
思路:题意为求出1~m所有数和n的gcd之和。显然gcd为n的因数。我们都知道gcd(a,b)= c,那么gcd(a/c,b/c)= 1。也就是说我们枚举n所有的因数k,然后去找1~m/k中和n/k互质的个数就是gcd为k的个数。这个直接容斥就行。
代码:
#include<iostream> #include<algorithm> #include<cstdio> #include<stdio.h> #include<string.h> #include<queue> #include<cmath> #include<map> #include<set> #include<vector> using namespace std; #define inf 0x3f3f3f3f #define lson l,mid,rt<<1 #define rson mid+1,r,rt<<1|1 #define mem(a,b) memset(a,b,sizeof(a)); #define lowbit(x) x&-x; typedef long long ll; typedef unsigned long long ull; const double eps = 1e-6; const int maxn = 1e5+5; const ll mod = 1e8+7; ll prime[maxn], p[maxn], pn; void init(){ pn = 0; memset(prime, 0, sizeof(prime)); for(ll i = 2; i < maxn; i++){ if(!prime[i]){ p[pn++] = i; for(ll j = i * i; j < maxn; j += i) prime[j] = 1; } } } ll y[maxn], tot; ll solve(ll r, ll n){ //返回1~r和n的gcd为1个数 tot = 0; ll N = n; for(int i = 0; p[i] * p[i] <= N && i < pn; i++){ if(N % p[i] == 0){ y[tot++] = p[i]; while(N % p[i] == 0) N /= p[i]; } } if(N > 1) y[tot++] = N; ll num = 0; for(ll i = 1; i < (1 << tot); i++){ ll val = 1, times = 0; for(ll j = 0; j < tot; j++){ if((1 << j) & i){ times++; val *= y[j]; } } if(times & 1){ num += r / val; } else{ num -= r / val; } } return r - num; } int main(){ ll n, m, num, ans = 0, cnt = 0, temp; init(); scanf("%lld%lld", &n, &m); for(ll i = 2; i <= sqrt(n); i++){ if(n % i == 0){ num = solve(m / i, n / i); ans += num * i; cnt += num; if(i * i != n){ temp = n / i; num = solve(m / temp, n / temp); ans += num * temp; cnt += num; } } } num = solve(m / n, 1); ans += num * n; cnt += num; ans += m - cnt; printf("%lld ", ans); return 0; }
以上是关于FJUT3565 最大公约数之和(容斥)题解的主要内容,如果未能解决你的问题,请参考以下文章