題解-bzoj2154Crash的數字表格 & bzoj2693 jzptab
Problem
bzoj2818-單組詢問-無權限
bzoj2693-多組詢問-需權限
洛谷1829-單組詢問-無權限
\(T\)組詢問(如果有),給定 \(n,m\),求
\[\sum_{i=1}^n\sum_{j=1}^mlcm(i,j) \pmod {100000009}\]
\(T\leq 10^4,N,M\leq 10^7\)
Solution
┗|`O′|┛ 這兩題花了我一整張草稿紙啊
首先明確將\(lcm\)轉成\(gcd\)會更好做:\(lcm(x,y)=\frac {xy}{\gcd(x,y)}\)
套路枚舉\(\gcd\):
\[Ans=\sum_d\frac 1d\sum_{d|a}\sum_{d|b}[\gcd(\frac ad,\frac bd)=1]ab\]
將 \(a,b\) 同時除以 \(d\)
\[Ans=\sum_d d\sum_{a=1}^{\frac nd}\sum_{b=1}^{\frac md}[\gcd(a,b)=1]ab\]
想到遇到互質的情況就莫反:
設置參量 \(n‘=\frac nd,m‘=\frac md\)
在參量意義下,構造函數
\[ f(x)=\sum_{a=1}^{n‘}\sum_{b=1}^{m‘}[\gcd(a,b)=x]ab\F(x)=\sum_{a=1}^{n‘}\sum_{b=1}^{m‘}[x|\gcd(a,b)]ab \]
這倆函數滿足\(F(x)=\sum_{x|n}f(n)\),根據莫反式有\(f(n)=\sum_{n|x}\mu(\frac xn)F(x)\)
將\(F(x)\)化簡
\[F(x)=\sum_{x|a}^{n‘}\sum_{x|b}^{m‘}ab=x^2(\sum_{a=1}^{\frac {n‘}x}a)(\sum_{b=1}^{\frac {m‘}x}b)\]
而\(Ans=\sum_dd\cdot f(1)\)
\[f(1)=\sum_d\mu(d)F(d)=\sum_d\mu(d)d^2(\sum_{a=1}^{\frac {n‘}d}a)(\sum_{b=1}^{\frac {m‘}d}b)\]
首先可以明確如果預處理 \(\mu(d)d^2\) 就可以整除分塊地在 \(O(\sqrt n)\) 的時間內算出這個式子
再接著考慮答案:\(Ans=\sum_dd\cdot f(1)\)
多組詢問
上面這個式子每次計算需要 \(O(n)\) 的時間,實測跑完 \(T=10^4\) 組需要 \(92s\),需要考慮優化
由於在單組詢問時是將帶入參量進行計算的,這樣雖然方便但不靈活,需要將參量化出來……以下省略若幹字(因為算到這裏後我又用了大半張草稿紙進行拆分合並 可能是因為我喜歡用參量吧,而且聽學長說這題有個簡便很多的方法)
首先將原式列出來(至於為什麽在整除意義下有\(\frac {\frac ab}c=\frac a{bc}\),可以想想\(\frac ab=\frac {a-(a\bmod b)}b\)):
\[Ans=\sum_dd\bigl [\sum_t\mu(t)t^2\cdot (\sum_{a=1}^{\frac n{dt}}a)(\sum_{b=1}^{\frac m{dt}}b)\bigr ]\]
設 \(T=dt,S(x)=\frac {x(x+1)}2\),並將式子內外翻轉可得
\[Ans=\sum_{T=1}^nS(\frac nT)S(\frac mT)\sum_{d|T}\mu(d)d^2\frac Td\\=\sum_{T=1}^nS(\frac nT)S(\frac mT)T\sum_{d|T}\mu(d)d\]
設函數 \(g(x)=x\sum_{d|x}\mu(d)d\),可得 \(Ans=\sum_{T=1}^nS(\frac nT)(\frac mT)g(T)\),這個東西就支持數論分塊了,總體復雜度為\(O(n+Q\sqrt n)\)
至於怎麽求 \(g(x)\),可以考慮只求 \(h(x)=\sum_{d|x}\mu(d)d\),這個東西是積性函數可以線性篩
具體地,在線性篩時,設當前篩數為 \(i\),質數為 \(p\),\(k=i\cdot p\)
- 若 \(p|i\),有 \(h(k)=h(i)\),因為新加入的質因子 \(p\) 在 \(i\) 中已經出現,如果它不可能單獨和其他質因子產生新的因數,而如果和其他的\(p\)因子在一起,\(\mu\)函數就會為 \(0\),所以有\(h(k)=h(i)\)
- 若 \(p\not |i\),有 \(h(k)=h(i)h(j)\),因為新加入的質因子 \(p\) 在 \(i\) 中尚未出現,所以它和其他所有質因子產生的因數 \(\mu\) 都會變號,而因子\(p\)也會相應地乘上去,至於保留原來因子的貢獻,\(h(p)\)在計算的時候會自帶一個 \(1\)
Code
bzoj-2154
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=10001009,p=20101009;
int pri[N],is[N],u[N],tp;
inline int sm(int x){
if(x&1)return (ll)x*(x+1>>1)%p;
return (ll)(x>>1)*(x+1)%p;
}
inline int F(int n,int m){
int res=0;
for(int i=1,j;i<=n;i=j+1){
j=min(n/(n/i),m/(m/i));
res=(res+(ll)(u[j]-u[i-1]+p)*sm(n/i)%p *sm(m/i))%p;
}return res;
}
int main(){
int n,m;
scanf("%d%d",&n,&m);
if(n>m)swap(n,m);u[1]=1;
for(int i=2;i<=n;++i){
if(!is[i])pri[++tp]=i,u[i]=-1;
for(int j=1,k;j<=tp and (k=i*pri[j])<=n;++j){
is[k]=1;
if(i%pri[j]==0){u[k]=0;break;}
u[k]=-u[i];
}
if(u[i]<0)u[i]=p-1;
u[i]=(u[i-1]+(ll)i*i%p*u[i])%p;
}
ll ans=0;
for(int i=1,j;i<=n;i=j+1){
j=min(n/(n/i),m/(m/i));
ans=(ans+(ll)(sm(j)-sm(i-1)+p)*F(n/i,m/i))%p;
}
printf("%lld\n",ans);
return 0;
}
bzoj-2693
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=10001009,p=100000009;
int pri[N],is[N],u[N],g[N],sm[N],tp;
int main(){
u[1]=g[1]=1;
for(int i=2;i<N;++i){
if(!is[i])pri[++tp]=i,u[i]=p-1,g[i]=((ll)u[i]*i+1)%p;
for(int j=1,k;j<=tp and (k=i*pri[j])<N;++j){
is[k]=1;
if(i%pri[j]==0){u[k]=0,g[k]=g[i];break;}
u[k]=p-u[i],g[k]=(ll)g[i]*g[pri[j]]%p;
}
if(u[i]<0)u[i]=p-1;
}
for(int i=1;i<N;++i){
u[i]=(u[i-1]+(ll)i*i%p*u[i])%p;
g[i]=(g[i-1]+(ll)i*g[i])%p;
sm[i]=(sm[i-1]+i<p?sm[i-1]+i:sm[i-1]+i-p);
}
int n,m,T;
scanf("%d",&T);
while(T--){
ll ans=0;scanf("%d%d",&n,&m);
if(n>m)swap(n,m);
for(int i=1,j;i<=n;i=j+1){
j=min(n/(n/i),m/(m/i));
ans=(ans+(ll)sm[n/i]*sm[m/i]%p*(g[j]-g[i-1]+p))%p;
}printf("%lld\n",ans);
}return 0;
}
題解-bzoj2154Crash的數字表格 & bzoj2693 jzptab