码迷,mamicode.com
首页 > 其他好文 > 详细

bzoj4916 神犇和蒟蒻

时间:2018-06-22 01:12:25      阅读:197      评论:0      收藏:0      [点我收藏+]

标签:line   void   整数   cpp   pac   ==   -o   put   输出   

神犇和蒟蒻

Time Limit: 10 Sec Memory Limit: 512 MB

Description

很久很久以前,有一只神犇叫yzy;
很久很久之后,有一只蒟蒻叫lty;

Input

请你读入一个整数N;1<=N<=1E9,A、B模1E9+7;

Output

请你输出一个整数\(A=\sum_{i=1}^N{\mu (i^2)}\)
请你输出一个整数\(B=\sum_{i=1}^N{\varphi (i^2)}\)

Sample Input

1

Sample Output

1

1




第一问不会的可以去找豆腐撞死了。。。。(撞之前你可以在想一想看能不能抢救一下。。。)
你输了 1 这道题就做一半了233.。。。
不闹了。。。。
\[\sum_{i=1}^n \phi(i^2)\]
\[=\sum_{i=1}^n \phi(i)i\]
\(f(x)= \phi(i)i \ \ \ \ \ \ \ \ \ \ \ \ \ f × id = h\)
\[h(x)=\sum_{d \mid n}f(d)\ \frac{d}{n}\]
\[=\sum_{d \mid n}\mu(d)n\]
\[=n^2\]
你很容易就可以求到了 \(id\)\(h\) 的前缀和,就可以杜教筛啦!




你列个式子出来看可以发现 \(\phi(i^2)=\phi(i)i\)
然后由于你有个杜教筛的幻想,你要去凑那个卷积。。。。
瞎搞了啊。。。我也很绝望啊。。。


#include<bits/stdc++.h>
using namespace std;
const int N = 2500000, mod = 1e9 + 7;
int tot, prime[N];
long long n, inv6, inv2, phi[N];
bool not_prime[N];
map<int, long long> p;

inline void prepare()
{
    phi[1] = 1;
    for(int i = 2; i < N; ++i){
        if(!not_prime[i]){
            prime[++tot] = i; phi[i] = i - 1;
        }
        for(int j = 1; prime[j] * i < N; ++j){
            not_prime[prime[j] * i] = true;
            if(i % prime[j] == 0){phi[i * prime[j]] = prime[j] * phi[i]; break;}
            phi[i * prime[j]] = phi[i] * (prime[j] - 1);
        }
    }
    for(int i = 2; i < N; ++i) phi[i] = (phi[i - 1] + phi[i] * i) % mod;
}

long long PHI(long long t)
{
    if(t < N) return phi[t];
    if(p[t]) return p[t];
    long long last, ret = t * (t + 1) % mod * (2 * t + 1) % mod * inv6 % mod;
    for(long long i = 2; i <= t; i = last + 1){
        last = min(t, t / (t / i));
        ret = (ret + mod - (i + last) * (last - i + 1) % mod * inv2 % mod * PHI(t / i) % mod) % mod; 
    }
    p[t] = ret; return ret;
}

inline void get_inv()
{
    int p = mod - 2; inv6 = 1; long long tmp = 6;
    while(p){
        if(p & 1)   inv6 = inv6 * tmp % mod;
        tmp = tmp * tmp % mod; p >>= 1;
    }
    p = mod - 2; inv2 = 1; tmp = 2;
    while(p){
        if(p & 1)   inv2 = inv2 * tmp % mod;
        tmp = tmp * tmp % mod; p >>= 1;
    }
}

int main()
{
    prepare(); get_inv();
    scanf("%d", &n); printf("1\n");
    printf("%lld", PHI(n)); 
    return 0;
}

bzoj4916 神犇和蒟蒻

标签:line   void   整数   cpp   pac   ==   -o   put   输出   

原文地址:https://www.cnblogs.com/LLppdd/p/9211459.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!