51nod 1237 最大公约数之和 V3

来源:互联网 发布:养羊软件 编辑:程序博客网 时间:2024/05/29 03:48

题目大意:

G=0;for(i=1;i<=N;i++)for(j=1;j<=N;j++){    G = (G + gcd(i,j)) % 1000000007;}

题解:

杜教筛。
这里提供两种反演姿势,之后我们会发现一个神奇的东西。
在此之前你得会杜教筛φ。

反演1:

ni=1nj=1gcd(i,j)
=2ni=1ij=1gcd(i,j)n(n+1)/2

ni=1ij=1gcd(i,j)
=nd=1d(ni=1ij=1(gcd(i,j)=d))
=nd=1d(n/di=1ij=1(gcd(i,j)=1))
=nd=1dφ(n/d)
=i=1φ(i)(n/ij=1j)
=i=1φ(i)n/i(n/i+1)/2

反演2:

必要结论:
d|ndμ(n/d) = φ(n)
证明:
狄利克雷卷积形式,老套路证明。
只需要证明:d|pqdμ(pq/d)=φ(pq)
d|pqdμ(pq/d)
=qk=0pkμ(pqk)
因为要使μ(pqk)不为0,所以缩小循环范围。
=qk=q1pkμ(pqk)
=pqpq1
=φ(pq)
那么根据积性函数的性质可得:
所以d|ndμ(n/d) = φ(n)

ni=1nj=1gcd(i,j)
=nd=1d(ni=1nj=1(gcd(i,j)=d))
中间莫比乌斯反演过程略。
=nd=1dn/di=1n/(di)2μ(i)
T=di,则
=nT=1n/T2d|Tdμ(n/d)
=nT=1n/T2φ(T)

坑爹的发现:

综合反演1和反演2会得到以下式子:
ni=1n/iφ(i)=n(n+1)/2
显然我不知道它有什么用,当做一个比较吊的结论吧。

反演2Code:

#include<cmath>#include<cstdio>#define ll long long#define fo(i, x, y) for(ll i = x; i <= y; i ++)using namespace std;const ll Maxn = 5000000, M = 12461987, ni_2 = 5e8 + 4, mo = 1e9 + 7;ll p[700000], phi[Maxn + 5], h[M][2];bool bz[Maxn + 5];ll hash(ll x) {    ll y = x % M;    while(h[y][0] != 0 && h[y][0] != x)        y = (y + 1) % M;    return y;}ll dg(ll n) {    if(n <= Maxn) return phi[n];    ll y = hash(n);    if(h[y][0] == n) return h[y][1];    ll t = n % mo;    h[y][1] = t * (t + 1) % mo * ni_2 % mo;    fo(i, 2, n) {        ll j = n / (n / i);        h[y][1] -= dg(n / i) * (j - i + 1) % mo;        i = j;    }    h[y][0] = n; h[y][1] = (h[y][1] % mo + mo) % mo;    return h[y][1];}ll n;int main() {    phi[1] = 1;    fo(i, 2, Maxn) {        if(!bz[i]) p[++ p[0]] = i, phi[i] = i - 1;        fo(j, 1, p[0]) {            ll k = i * p[j];            if(k > Maxn) break;            bz[k] = 1;            if(i % p[j] == 0) {                phi[k] = phi[i] * p[j];                break;            }            phi[k] = phi[i] * (p[j] - 1);        }    }    fo(i, 1, Maxn) phi[i] = (phi[i - 1] + phi[i]) % mo;    ll ans = 0;    scanf("%lld", &n);    fo(i, 1, n)  {        ll j = n / (n / i), k = n / i % mo;        k = (k * k) % mo;        ans += k * (dg(j) - dg(i - 1) + mo) % mo;        ans %= mo;        i = j;    }    printf("%lld", ans);}
原创粉丝点击