1. 程式人生 > >SHU-“盛大遊戲杯”第15屆上海大學程式設計聯賽夏季賽暨上海高校金馬五校賽-J-膜一下將帶給你好運

SHU-“盛大遊戲杯”第15屆上海大學程式設計聯賽夏季賽暨上海高校金馬五校賽-J-膜一下將帶給你好運

ACM模版

描述

描述

題解

這個題是一道推導題,推導過程如下:

首先,我們應該都知道的是

n=d|nphi(d) 所以呢,i=1ni=i=1nd|iphi(d) goon… i=1ni=i=1nphi(i)ni 此時,我們來分析題目中的式子,設 F(x)=ni=1phi(i)ni,恰好等於上述 ni=1

所以呢,我們的結果也就出來了,先預處理前 232phi,然後求等差數列的和,減去前 232 個,接著求出後 232phi,並減去,當然這裡要注意肯定不是直接減去,還要先乘以 ni 再減去,就這樣,沒問題了。

程式碼

#include <iostream>
#include <cmath> #define clr(x,y) memset(x, y, sizeof(x)) using namespace std; typedef long long ll; const int MOD = 1e9 + 7; const int MAGIC = 233; int n; int phi[MAGIC]; int get_phi(int x) { unsigned i, res = x; // unsigned == unsigned int for (i = 2; i < (int)sqrt(x * 1.0
) + 1; i++) { if (!(x % i)) { res = res / i * (i - 1); while (!(x % i)) { x /= i; // 保證i一定是素數 } } } if (x > 1) { res = res / x * (x - 1); } return res; } void init() { for (int
i = 1; i <= MAGIC; i++) { phi[i] = i; } for (int i = 2; i <= MAGIC; i += 2) { phi[i] /= 2; } for (int i = 3; i <= MAGIC; i += 2) { if (phi[i] == i) { for (int j = i; j <= MAGIC; j += i) { phi[j] = phi[j] / i * (i - 1); } } } } int main() { init(); int t; cin >> t; while (t--) { cin >> n; int ans = (ll)n * (1 + n) / 2 % MOD; for (int i = 1; i < MAGIC; i++) { ans = (ans - (ll)phi[i] * (n / i) % MOD + MOD) % MOD; } for (int i = n; i > n - MAGIC; i--) { ans = (ans - (ll)get_phi(i) * (n / i) % MOD + MOD) % MOD; } cout << ans << endl; } return 0; }