HDU6706(huntian oy 公式+杜教筛板子)

题目
HDU6706(huntian oy 公式+杜教筛板子)_第1张图片先放题解的截图
HDU6706(huntian oy 公式+杜教筛板子)_第2张图片


下面就是我自己写的啦 几乎一样
HDU6706(huntian oy 公式+杜教筛板子)_第3张图片

在这里插入图片描述
HDU6706(huntian oy 公式+杜教筛板子)_第4张图片

#include
#include
using namespace std;
using namespace std::tr1;
typedef long long ll;
const int N=5e6+5,mod=1e9+7,Max=2147483647,inv2=500000004,inv6=166666668;
int is[N+5],prime[N+5];
int phid[N+5];
void init(){
    phid[1]=1;int tot=0;
    for(int i=2;i<=N;++i){
        if(!is[i]) prime[++tot]=i,phid[i]=(ll)i*(i-1)%mod;
        for(int j=1;j<=tot&&(ll)i*prime[j]<=N;++j){
            int t=i*prime[j];is[t]=1;
            if(i%prime[j]==0) {phid[t]=(ll)phid[i]*prime[j]%mod*prime[j]%mod;break;}//第一个prime[j]是phi[t]=phi[i]*prime[j]. 第二个是t=i*prime[j];
            phid[t]=(ll)phid[i]*(prime[j]-1)%mod*prime[j]%mod;
        }
    }
    for(int i=2;i<=N;++i) phid[i]+=phid[i-1],phid[i]%=mod;
}
unordered_map<int,int>ans_phid;
inline int cal(int l,int r){
    return (ll)((l+r)%mod)*(r-l+1)%mod*inv2%mod;
}
inline int f_phid(int n){
    if(n<=N) return phid[n];
    if(ans_phid[n]) return ans_phid[n];
    ll res=(ll)n*(n+1)%mod*((2*n+1)%mod)%mod*inv6%mod;
    for(int l=2,r;l<=n&&r<Max;l=r+1)
        r=n/(n/l),res-=(ll)cal(l,r)*f_phid(n/l)%mod,res%=mod;
    return ans_phid[n]=(res+mod)%mod;
}
inline int solve(int n){
    return (ll)(f_phid(n)-1)*inv2%mod;//注意不要爆int呀
}
int main(){
    init();int T;scanf("%d",&T);
    while(T--){
        int n,a,b;scanf("%d%d%d",&n,&a,&b);
        printf("%d\n",solve(n));
    }
}

你可能感兴趣的:(数学==杜教筛)