SHU-“盛大游戏杯”第15届上海大学程序设计联赛夏季赛暨上海高校金马五校赛-J-膜一下将带给你好运

来源:互联网 发布:catia软件销售怎么样 编辑:程序博客网 时间:2024/05/16 10:14

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;}
阅读全文
0 0
原创粉丝点击