[BZOJ3512]DZY loves Math IV-數論
【題目地址】
簡易題意
給定,求下面式子在意義下的值:
和這道題很像,但是這裡,資料範圍完全不同了,而且只有單次詢問,所以我們考慮很小,所以從後半部分下手。
我們令,那麼最後的式子就是,所以考慮如何快速求取函式。
現在只看這個式子:
考慮如何把拆開,根據求取的式子:
我們提取每種質因子的一個出來,那麼就變成了:
因為在例如時,,而每個質因子之間可以分開獨立考慮,所以上面式子成立。
而的證明看這裡:
摘取自友鏈部落格【IN-there-by hdxrie】
所以我們把變成後,原式變成如下:
由於中全部是一次質因子的乘積,所以:
這裡,我們考慮將其拆開,一部分是屬於的質因子,而只屬於的也就是除去公共質因子的部分,相當於屬於的,但是最後還少了個,再乘上即可。而且這裡由於的所有質因子都只出現一次,所以除以了後肯定與互質,不會有重複的。
然後我們根據,將後面的,所以:
由於中每個質因子只出現一次,所以我們可以將乘到中的每一項,此時,由於肯定與每個互質,根據積性函式的定義:
其實就相當於等於:
因為列舉,是一樣的。
所以我們繼續化簡:
我們交換列舉順序即可得到:
然後可以發現後面部分就是一個子問題了,所以遞迴求就好啦。
複雜度和杜教篩類似。
程式碼~~
#include<vector>
#include<map>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
#define lowbit(a) ((a)&(-(a)))
using namespace std;
const int M=1e6+10,N=1e5+10,S=1<<20;
const ll Mod=1e9+7;
ll prime[N],phi[M],F[M],last[M],cnt;
bool vis[M];
int bit[S];
void init(){
phi[1]=1;
bit[1]=0;
for(int i=1;i<=19;i++)bit[1<<i]=i;
for(ll i=2;i<M;i++){
if(!vis[i]){
prime[++cnt]=i;
phi[i]=i-1;last[i]=1;\\last記錄上次的質因子
}
for(ll j=1,v;j<=cnt&&i*prime[j]<M;j++){
v=i*prime[j];
vis[v]=1;last[v]=i;
if(!(i%prime[j])){
phi[v]=phi[i]*prime[j];
break;
}
phi[v]=phi[i]*phi[prime[j]];
}
}
for(int i=1;i<M;i++)F[i]=(F[i-1]+phi[i])%Mod;
}
map <ll,ll> mp_phi;
map <ll,ll> mp_cal[N];
ll calc_phi(ll n){
if(n<M) return F[n];//杜教篩求phi的字首和
if(mp_phi.count(n)) return mp_phi[n];
ll ans=((n*(n+1ll))>>1)%Mod;
for(ll i=2,j;i<=n;i=j+1){
j=(n/(n/i));
ans=(ans-((j-i+1)%Mod)*calc_phi(n/i)%Mod)%Mod;
}
if(ans<0)ans+=Mod;
return mp_phi[n]=ans;
}
map <ll,ll> mp_p;
ll Getp(ll a){
if(a<M) return phi[a];
if(mp_p.count(a)) return mp_p[a];
ll t=a,tmp=a;
for(ll j=2;j*j<=a;j++){
if(t%j==0) {
a=a/j*(j-1);
while(t%j==0) t/=j;
}
}if(t>1) a=a/t*(t-1);
return mp_p[tmp]=a;
}//求單獨一個phi
ll calc(ll n,ll m){
if(n==1) return calc_phi(m);//n=1時就是phi的字首和
if(m==1) return Getp(n);//m=1就是一個phi
if(!m||!n) return 0;//為0就返回0
if(mp_cal[n].count(m)) return mp_cal[n][m];//記憶化
vector <ll> div;div.clear();
ll ans=0,x=1,y,w=1,tc=n;
while(n>1){
y=n/last[n];w*=y;n=last[n];
div.push_back(y);
while(!(n%y))n/=y,x*=y;
}
//w為a,x為b
n=tc;
int sze=div.size(),up=1<<sze;
for(int i=0;i<up;i++){
ll d=1ll;
for(int j=i;j>0;j-=lowbit(j))d*=div[bit[lowbit(j)]];
ans=(ans+(Getp(w/d)*calc(d,m/d))%Mod)%Mod;
}//2進位制列舉約數的質因子組成
ans=(ans*x)%Mod;//最後乘以b
return mp_cal[n][m]=ans;
}
int n,m;ll ans;
int main(){
init();
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)ans=(ans+calc(i,m))%Mod;//累加
printf("%lld\n",ans);
return 0;
}
另一種實現方式,較為簡單,原理差不多:
掛個連結Orz%%%-IN
End
相關文章
- cf444E. DZY Loves Planting(並查集)並查集
- 學長小清新題表之UOJ 14.DZY Loves Graph
- UA MATH563 概率論的數學基礎 鞅論初步8 鞅收斂定理H5
- UA MATH563 概率論的數學基礎 鞅論初步9 分支過程簡介H5
- Js Math隨機數JS隨機
- JavaScript Math(數學) 參考JavaScript
- UA MATH563 概率論的數學基礎 中心極限定理5 Renyi定理H5
- 使用Math類生成隨機數隨機
- [BJDCTF2020]Mark loves catTF2
- UA MATH563 概率論的數學基礎 中心極限定理14 Kolmogorov maximal inequalityH5Go
- Math.round(),Math.ceil(),Math.floor
- UA MATH563 概率論的數學基礎 中心極限定理12 強大數定律 版本2:Etemadi定理H5
- [ARC058F] Iroha Loves Strings
- OI loves Algorithm——字尾陣列Go陣列
- UA MATH563 概率論的數學基礎 中心極限定理8 弱大數定律 Bernstein多項式逼近H5
- UA MATH563 概率論的數學基礎 中心極限定理15 Kolmogorov 0-1律H5Go
- 數論——數論分塊
- js可以使用 Math(算數) 物件生成隨機數JS物件隨機
- CodeTON Round 9 D.Shohag Loves GCDGC
- Math
- Python分享之數學與隨機數 (math包,random包)Python隨機random
- UA MATH563 概率論的數學基礎 中心極限定理23 概率測度族的緊性H5
- UA MATH563 概率論的數學基礎 中心極限定理7 Kolmogorov extension theorem及其擴充套件H5GoREM套件
- UA MATH563 概率論的數學基礎 中心極限定理4 獨立一元隨機變數的性質H5隨機變數
- Math類產生隨機數後保留一位小數隨機
- 數論
- Math For Programmers
- Math類
- UA MATH523A 實分析3 積分理論15 乘積測度H5
- C# Math 中的常用的數學運算C#
- Python標準庫12 數學與隨機數 (math包,random包)Python隨機random
- 洛谷 P4829 kry loves 2048——題解
- 【Ynoi 2019 模擬賽】Yuno loves sqrt technology III
- UA MATH563 概率論的數學基礎 中心極限定理6 獨立隨機變數的和與Kolmogorov擴充套件定理H5隨機變數Go套件
- 數論(1):素數
- 數學 之 數論
- JavaScript Math.trunc vs Math.floor All In OneJavaScript
- 數論板子