題目連接
\(T ≤ 100\) \(n ≤ 500\)
唔,看數據範圍,暴力可過.
時間複雜度\(O(T * n ^ 2)\)ios
#include <iostream> #include <cstdio> using namespace std; int gcd(int a,int b) { while(b ^= a ^= b ^= a %= b) ; return a; } int main() { int n = 1; while(scanf("%d",&n) && n) { long long ans = 0; for(int i = 1;i <= n;++ i) { for(int j = i + 1;j <= n;++ j) { ans += 1LL * gcd(i,j); } } printf("%lld\n",ans); } }
然則還能夠用莫比烏斯反演spa
#include <iostream> #include <cstdio> #define ll unsigned long long const ll maxN= 1000+6;; bool vis[maxN]; ll prime[maxN]; ll mu[maxN]; ll sum[maxN]; void init() { ll num = 0; vis[1] = 1; mu[1] = 1; for(ll i = 2;i <= 1000;++ i) { if( !vis[i] ) { prime[++ num] = i; mu[i] = -1; } for(ll j = 1;j <= num && prime[j] * i <= 1000;++ j) { vis[i * prime[j]] = true; if(i % prime[j] == 0) { mu[i * prime[j]] = 0; break; } mu[i * prime[j]] = -mu[i]; } } for(ll i = 1;i <= 1000;++ i) sum[i] = sum[i - 1] + mu[i]; return; } ll slove(ll n,ll k) { ll ans = 0; n /= k; for(ll l = 1,r;l <= n;l = r + 1) { r = n / (n / l); ans += ( sum[r] - sum[l - 1] ) * (n / l) * (n / l); } return ans; } int main() { ll n = 1; init(); while(scanf("%llu",&n) && n) { ll ans = 0; for(ll i = 1;i <= n;++ i) { ans += i * slove(n,i); } printf("%llu\n",(ans - (n + 1) * n / 2) / 2); } return 0; }