51Nod1220約數之和-數論
推了一下午,寫又花了一晚上,XD,自己還是太菜了
【題目地址】
題意簡述
單組詢問,給定一個,求下面的式子的值在意義下的值。
其中表示的約數和,例如
我們按照[SDOI2015]約數個數和的套路先考慮如何轉換,其實也可以考慮對映,所以可以寫成如下形式:
簡略證明:
同樣,每個質因數直間互不影響,所以我們考慮,對於一個質因數,其中(這裡和上面連結的那道題一樣,),所以對於當時,的中肯定含有,而中也只含有(此時僅對於這一個質因數),所以此時可以將因子為的取完,而另一部分則是在時,的了,而肯定含有,而算時,是在同時為的情況下,只會算一次,所以不用減去它。那麼此時對於因子的所有情況就算完了,而每次計算的時候都是一個沒有因子,一個有,所以要滿足,將其應用到所有的質因子上,就可以得到上面的式子。
那麼原式就可以轉化成:
我們用莫比烏斯反演的套路將其進行變形:
而此時我們看後面那一大坨,分開考慮:
我們把那一個拿出去,然後令,其實根據前面連結的經驗,我們很容易知道:
證明:
首先可以看出每一個因子乘以出現次數,然後就是前面連結裡的證明了。
對於另一個,我們同樣轉換:
其實我們令,那麼可以得到:
此時要有貢獻,條件為,我們將其變形可以得到:
所以我們改變列舉順序,得到:
所以原式變成了:
此時我們需要用杜教篩篩,我們令,那麼,所以直接套入杜教篩公式,得到:
前面用杜教篩,後面預處理加的算即可,複雜度
#include<map>
#include<cstdio>
#include<cstring>
#include<algorithm>
#pragma GCC optimize(2)
#define ll long long
using namespace std;
const ll Mod=1e9+7;
const int M=2e6+10,MAX=2e6;
ll n,m,inv_2,cnt;
ll prime[M],mu[M],F[M],B[M];
ll &Rec(ll x){
if(x<=MAX) return F[x];
else return B[n/x];
}
bool vis[M];
ll s[M],p[M],sum[M],bum[M];
ll &Rec2(ll x){
if(x<=MAX) return sum[x];
else return bum[n/x];
}//空間儲存技巧
ll fpow(ll a,ll b){
ll res=1;
for(;b;b>>=1,a=(a*a)%Mod){
if(b&1)res=(res*a)%Mod;
}
return res;
}
void init(){
memset(bum,-1,sizeof(bum));
memset(B,-1,sizeof(B));
s[1]=mu[1]=1;inv_2=fpow(2,Mod-2);
for(int i=2;i<=MAX;i++){
if(!vis[i]){
prime[++cnt]=i;
s[i]=p[i]=1+i;
mu[i]=-1;
}
for(int j=1,v;j<=cnt&&i*prime[j]<=MAX;j++){
v=i*prime[j];
vis[v]=1;
if(!(i%prime[j])){
s[v]=s[i]/p[i]*(p[i]*prime[j]+1);
p[v]=p[i]*prime[j]+1;
break;
}
mu[v]=-mu[i];
s[v]=s[i]*s[prime[j]];
p[v]=1+prime[j];
}
}
for(int i=1;i<=MAX;i++){
sum[i]=(sum[i-1]+s[i]%Mod)%Mod;
F[i]=(F[i-1]+(i*mu[i])%Mod)%Mod;
if(F[i]<0)F[i]+=Mod;
}
}
ll S(ll x){if(x>=Mod)x%=Mod;return (x*(x+1)%Mod)*inv_2%Mod;}
ll Sarea(ll L,ll R){return ((S(R)-S(L-1))%Mod+Mod)%Mod;}
ll GetS(ll x){
ll &ans=Rec2(x);
if(ans!=-1) return ans;
ans=0;
for(ll i=1,j;i<=x;i=j+1){
j=(x/(x/i));
ans=(ans+Sarea(i,j)*(x/i)%Mod)%Mod;
}
return ans;
}
ll calc(ll x){
ll &ans=Rec(x);
if(ans!=-1) return ans;
ans=1;
for(ll i=2,j;i<=x;i=j+1){
j=(x/(x/i));
ans=(ans-Sarea(i,j)*calc(x/i)%Mod)%Mod;
}
if(ans<0)ans+=Mod;
return ans;
}
ll Carea(ll L,ll R){return ((calc(R)-calc(L-1))%Mod+Mod)%Mod;}
ll Sqr(ll a){return a*a%Mod;}
ll solve(ll x){
ll ans=0;
for(ll i=1,j;i<=x;i=j+1){
j=(x/(x/i));
ans=(ans+Carea(i,j)*Sqr(GetS(x/i))%Mod)%Mod;
}
return ans;
}
int main(){
init();
scanf("%lld",&n);
printf("%lld\n",solve(n));
return 0;
}
另外一種類似的推導方式【IN-orz%%%】
相關文章
- AcWing871. 約數之和
- abc172D 約數之和
- 數論——質數與約數
- 兩數之和,三數之和,最接近的三數之和,四數之和
- 兩數之和
- 三數之和
- LeetCode - 兩數之和LeetCode
- 兩數之和(TwoSum)
- LeetCode:兩數之和LeetCode
- 整數劃分為多數之和
- 18_四數之和
- LeetCode-兩數之和LeetCode
- 1. 兩數之和
- 633. 平方數之和
- leetcode #1 兩數之和LeetCode
- LeetCode 1 兩數之和LeetCode
- LeetCode之兩數之和LeetCode
- 15.三數之和
- 57. 三數之和 &&
- 洛谷P1403 [AHOI2005]約數研究【數論】
- 尤拉計劃725:數位之和數
- [SDOI2015]約數個數和-[BZOJ4176]Lucas的數論-題解
- 數論——數論分塊
- LeetCode 15.三數之和LeetCode
- 兩數之和詳細解答
- 力扣之兩數之和力扣
- LeetCode15.三數之和LeetCode
- LeetCode15. 三數之和LeetCode
- leetcode-0001 兩數之和LeetCode
- LeetCode 1. 兩數之和LeetCode
- LeetCode18:四數之和LeetCode
- LeetCode: Two sum(兩數之和)LeetCode
- Sum of Square Numbers 平方數之和
- 演算法-兩數之和演算法
- LeetCode-1. 兩數之和LeetCode
- 程式碼隨想錄演算法訓練營第七天 | 四數之和、贖金信、三數之和、四數之和2演算法
- 約數
- 質數與約數