HDU 5608 - function

HDU 5608 - function php

套路題c++

圖片來自:git

 https://blog.csdn.net/V5ZSQ/article/details/52116285spa

 

杜教篩思想,根號遞歸下去。.net

先搞出前綴和g(n)=∑f(i)code

而後尋求遞歸。∑g(n/i)=常數blog

這一步要運用給出的f(i)的關係,幹掉f遞歸

具體:圖片

向枚舉約數轉化,不斷交換求和,交換統計貢獻的部分。經過數學意義變成枚舉約數get

 

而後相似杜教篩便可

f的前1000000項,調和級數枚舉約數減去貢獻

#include<bits/stdc++.h>
#define reg register int
#define il inline
#define fi first
#define se second
#define mk(a,b) make_pair(a,b)
#define numb (ch^'0')
using namespace std;
typedef long long ll;
template<class T>il void rd(T &x){
    char ch;x=0;bool fl=false;
    while(!isdigit(ch=getchar()))(ch=='-')&&(fl=true);
    for(x=numb;isdigit(ch=getchar());x=x*10+numb);
    (fl==true)&&(x=-x);
}
template<class T>il void ot(T x){x/10?ot(x/10):putchar(x%10+'0');}
template<class T>il void prt(T a[],int st,int nd){for(reg i=st;i<=nd;++i) printf("%lld ",a[i]);putchar('\n');}

namespace Miracle{
const int mod=1e9+7;
const int M=1000000+6;
int t,n;
int f[M];
int qm(int x,int y){
    int ret=1;while(y){
        if(y&1) ret=(ll)ret*x%mod;x=(ll)x*x%mod;y>>=1;
    }return ret;
}
int ad(int x,int y){
    return x+y>=mod?x+y-mod:x+y;
}
void sieve(int n){
    for(reg i=1;i<=n;++i) f[i]=(ll)(i-1)*(i-2)%mod;
    for(reg i=1;i<=n;++i){
        for(reg j=i+i;j<=n;j+=i){
            f[j]=ad(f[j],mod-f[i]);
        }
    }
    for(reg i=1;i<=n;++i) f[i]=ad(f[i],f[i-1]);
}
map<int,int>mp;
int inv6;
int sol(int n){
    if(n<=M-5) return f[n];
    if(mp.find(n)!=mp.end()) return mp[n];
    ll ret=(ll)(n-1)*n%mod*(2*n-1)%mod*inv6%mod;
    ret=ad(ret,mod-(ll)n*(n-1)/2%mod);
    for(reg i=2,x=0;i<=n;i=x+1){
        x=(n/(n/i));
        ret=ad(ret,mod-(ll)(x-i+1)*sol(n/i)%mod);
    }
    return mp[n]=ret;
}
int main(){
    sieve(M-5);
    inv6=qm(6,mod-2);
    rd(t);
    while(t--){
        rd(n);printf("%d\n",sol(n));
    }
    return 0;
}

}
signed main(){
    Miracle::main();
    return 0;
}

/*
   Author: *Miracle*
   Date: 2019/3/8 11:16:20
*/
相關文章
相關標籤/搜索