[bzoj4916] 神犇和蒟蒻

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

solution

杜教筛基础题.

对于第一问,由于当\(i\geqslant 2\)的时候\(\mu(i^2)=0\),所以直接puts("1")就好了.


\[ f(n)=\varphi(n^2)=\varphi(n)*n\\ S(n)=\sum_{i=1}^{n}f(i) \]
然后把杜教筛的套路式子搬出来:
\[ S(n)=\sum_{i=1}^{n}(f*g)(i)-\sum_{i=2}^{n}g(i)S(\lfloor\frac{n}{i}\rfloor) \]
然后考虑凑出这个\(g\)
\[ (f*g)(n)=\sum_{i|n}i*\varphi(i)*g(\frac{n}{i}) \]
看到这个系数\(i\)很不爽,考虑把他消掉,令\(g(n)=n\),得:
\[ (f*g)(n)=\sum_{i|n}i*\varphi(i)*\frac{n}{i}=n*\sum_{i|n}\varphi(i)=n^2 \]
然后发现这个东西的前缀和很好求,就直接带到套路式里得:
\[ S(n)=\frac{n(n+1)(2n+1)}{6}-\sum_{i=2}^niS(\lfloor\frac{n}{i}\rfloor) \]
然后记忆化一下,递归求这个,线筛出前\(1e7\)就做完了.

#include<bits/stdc++.h>
using namespace std;

#define int long long 

void read(int &x) {
    x=0;int f=1;char ch=getchar();
    for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-f;
    for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0';x*=f;
}

void print(int x) {
    if(x<0) x=-x,putchar('-');
    if(!x) return ;print(x/10),putchar(x%10+48);
}
void write(int x) {if(!x) putchar('0');else print(x);putchar('\n');}

const int maxn = 1e7+1;
const int mod = 1e9+7;

int phi[maxn],pri[maxn],vis[maxn],n,tot,inv2,inv6;

void sieve() {
    phi[1]=1;
    for(int i=2;i<maxn;i++) {
        if(!vis[i]) pri[++tot]=i,phi[i]=i-1;
        for(int t,j=1;j<=tot&&i*pri[j]<maxn;j++) {
            vis[t=i*pri[j]]=1;
            if(!(i%pri[j])) {phi[t]=phi[i]*pri[j];break;}
            phi[t]=phi[i]*phi[pri[j]];
        }
    }
    for(int i=1;i<maxn;i++) phi[i]=(phi[i-1]+phi[i]*i)%mod;
}

map<int,int > Phi;

int qpow(int a,int x) {
    int res=1;
    for(;x;x>>=1,a=a*a%mod) if(x&1) res=res*a%mod;
    return res;
}

int calc(int n) {return n%mod*(n%mod+1)%mod*inv2%mod;}

int sum(int n) {
    if(n<maxn) return phi[n];
    if(Phi[n]) return Phi[n];
    int res=n*(n+1)%mod*(n+n+1)%mod*inv6%mod;
    int T=2;//printf("%lld\n",Phi[n]);
    while(T<=n) {
        int pre=T;T=n/(n/T);
        res=(res-sum(n/T)*(calc(T)-calc(pre-1))%mod)%mod;T++;
    }
    return Phi[n]=(res%mod+mod)%mod;
}

signed main() {
    sieve();inv2=qpow(2,mod-2);inv6=qpow(6,mod-2);
    int n;read(n);write(1ll),write(sum(n));
    return 0;
}

转载于:https://www.cnblogs.com/hbyer/p/10071615.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值