一定要先%mmh学长
例①:
P4213 【模板】杜教筛(Sum):

题目描述
给定一个正整数N(N≤231−1)

ans1= ∑φ(i) from 1 to n

ans2= ∑μ(i) from 1 to n

输入格式
一共T+1行 第1行为数据组数T(T<=10) 第2~T+1行每行一个非负整数N,代表一组询问

输出格式
一共T行,每行两个用空格分隔的数ans1,ans2

输入输出样例
输入 #1 复制
6
1
2
8
13
30
2333
输出 #1 复制
1 1
2 0
22 -2
58 -3
278 -3
1655470 2

有点卡时,要把不需要ll的全部改成int。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<string>
#include<queue>
#include<map>
#include<unordered_map>
#define ll long long
#define llu unsigned ll
#define iu unsigned int
using namespace std;
const int maxn=6000100;
int prime[maxn],cnt;
bool ha[maxn];
int mu[maxn];
ll p[maxn];
unordered_map<int,ll>ansp;
unordered_map<int,int>ansmu;


void Prime(void)
{
    ha[1]=true;
    mu[1]=p[1]=1;
    for(int i=2;i<maxn;i++)
    {
        if(!ha[i])
        {
            prime[cnt++]=i;
            mu[i]=-1;
            p[i]=i-1;
        }
        for(int j=0;j<cnt&&prime[j]*i<maxn;j++)
        {
            ha[i*prime[j]]=true;
            if(i%prime[j]==0)
            {
                mu[i*prime[j]]=0;
                p[i*prime[j]]=p[i]*prime[j];
                break;
            }
            mu[i*prime[j]]=-mu[i];
            p[i*prime[j]]=p[i]*p[prime[j]];
        }
    }
    for(int i=2;i<maxn;i++)
        mu[i]+=mu[i-1],p[i]+=p[i-1];
}

int sum_mu(int n)
{
    if(n<maxn) return mu[n];
    if(ansmu[n]) return ansmu[n];
    int ans=0;
    for(iu l=2,r;l<=n;l=r+1)//n为最值的时候,r+1可能爆int
    {
        r=n/(n/l);
        ans+=(r-l+1)*sum_mu(n/l);
    }
    ansmu[n]=1-ans;
    return ansmu[n];
}

ll sum_p(int n)
{
    if(n<maxn) return p[n];
    if(ansp[n]) return ansp[n];
    ll ans=0;
    for(iu l=2,r;l<=n;l=r+1) //n为最值的时候,r+1可能爆int
    {
        r=n/(n/l);
        ans+=1ll*(r-l+1)*sum_p(n/l);
    }
    ansp[n]=1ll*n*(1ll*n+1)/2ll-ans;//这里爆不了ll,但是n为最值的时候,n+1会爆int
    return ansp[n];
}

signed main(void)
{
    Prime();
    int t;
    scanf("%d",&t);
    while(t--)
    {
        int n;
        scanf("%d",&n);
        printf("%lld %d\n",sum_p(n),sum_mu(n));
    }
    return 0;
}

例②: HDU - 6706 :huntian oy :
One day, Master oy created a new function to celebrate his becoming a ‘huntian’ in majsoul.

f(n,a,b)=∑(from 1 to n)∑(from 1 to i) gcd(ia−ja,ib−jb)[gcd(i,j)=1]%(109+7)

Given n, a and b, Master oy wanted Newbie jj who was still a ‘chuxin’ to answer the value of f(n,a,b).
Input
There are multiple test cases.

The first line contains an integer T, indicating the number of test cases.

For each test case, there are three positive integers n, a and b which are separated by spaces. It’s guaranteed that a and b are coprime.

1≤n,a,b≤1e9

T=1e4, but there are only 10 test cases that n is over 1e6.
Output
For each test case, an integer in one line representing your answer.
Sample Input
2
1 2 3
100 2 3
Sample Output
0
101542

题解:就是求 ∑(from 1 to n) i*φ(i)。
当时公式化出来了,也知道是杜教筛,但是不会杜教筛。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<string>
#include<queue>
#include<map>
#include<unordered_map>
#define ll long long
#define llu unsigned ll
#define iu unsigned int
using namespace std;
const int maxn=3000100;
const int mod=1e9+7;
ll prime[maxn],p[maxn],cnt;
ll inv2,inv6;
bool ha[maxn];
unordered_map<ll,ll>ansp;

ll mypow(ll a,ll b)
{
    ll ans=1;
    while(b)
    {
        if(b&1) ans=ans*a%mod;
        a=a*a%mod;
        b>>=1;
    }
    return ans;
}

void Prime(void)
{
    ha[1]=true;
    p[1]=1;
    for(int i=2;i<maxn;i++)
    {
        if(!ha[i])
        {
            prime[cnt++]=i;
            p[i]=i-1;
        }
        for(int j=0;j<cnt&&prime[j]*i<maxn;j++)
        {
            ha[i*prime[j]]=true;
            if(i%prime[j]==0)
            {
                p[i*prime[j]]=p[i]*prime[j];
                break;
            }
            p[i*prime[j]]=p[i]*p[prime[j]];
        }
    }
    for(int i=2;i<maxn;i++)
        p[i]=(p[i]*i+p[i-1])%mod;
}


ll sum(ll n)
{
    if(n<maxn) return p[n];
    if(ansp[n]) return ansp[n];
    ll ans=(n)*(n+1)%mod*(n*2%mod+1)%mod*inv6%mod;
    for(ll l=2,r;l<=n;l=r+1)
    {
        r=n/(n/l);
        ans-=(r-l+1)*(l+r)%mod*inv2%mod*sum(n/l)%mod;
        ans=(ans%mod+mod)%mod;
    }
    ansp[n]=ans;
    return ansp[n];
}

signed main(void)
{
    Prime();
    inv2=mypow(2,mod-2);
    inv6=mypow(6,mod-2);
    int t;
    scanf("%d",&t);
    while(t--)
    {
        ll n,a,b;
        scanf("%lld%lld%lld",&n,&a,&b);
        printf("%lld\n",(sum(n)-1+mod)%mod*inv2%mod);
    }
    return 0;
}