日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

luogu P4240 毒瘤之神的考验(莫比乌斯反演+递推前缀和+数论分块)

發布時間:2023/12/3 编程问答 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 luogu P4240 毒瘤之神的考验(莫比乌斯反演+递推前缀和+数论分块) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

problem

洛谷鏈接

solution

∑i=1n∑j=1mφ(ij)=∑i=1n∑j=1mφ(i)φ(j)gcd?(i,j)φ(gcd?(i,j))\sum_{i=1}^n\sum_{j=1}^m\varphi(ij)=\sum_{i=1}^n\sum_{j=1}^m\frac{\varphi(i)\varphi(j)\gcd(i,j)}{\varphi{(\gcd(i,j))}}i=1n?j=1m?φ(ij)=i=1n?j=1m?φ(gcd(i,j))φ(i)φ(j)gcd(i,j)?=∑d=1min?(n,m)dφ(d)∑i=1n∑j=1mφ(i)φ(j)[(i,j)=d]=\sum_{d=1}^{\min(n,m)}\fracozvdkddzhkzd{\varphi(d)}\sum_{i=1}^n\sum_{j=1}^m\varphi(i)\varphi(j)\big[(i,j)=d\big]=d=1min(n,m)?φ(d)d?i=1n?j=1m?φ(i)φ(j)[(i,j)=d]=∑d=1min?(n,m)dφ(d)∑i=1?nd?∑j=1?md?φ(id)φ(jd)[(i,j)=1]=\sum_{d=1}^{\min(n,m)}\fracozvdkddzhkzd{\varphi(d)}\sum_{i=1}^{\lfloor\frac{n}ozvdkddzhkzd\rfloor}\sum_{j=1}^{\lfloor\frac{m}ozvdkddzhkzd\rfloor}\varphi(id)\varphi(jd)\big[(i,j)=1\big]=d=1min(n,m)?φ(d)d?i=1?dn???j=1?dm???φ(id)φ(jd)[(i,j)=1]=∑d=1min?(n,m)dφ(d)∑i=1?nd?∑j=1?md?φ(id)φ(jd)∑k∣(i,j)μ(k)=\sum_{d=1}^{\min(n,m)}\fracozvdkddzhkzd{\varphi(d)}\sum_{i=1}^{\lfloor\frac n d\rfloor}\sum_{j=1}^{\lfloor\frac m d\rfloor}\varphi(id)\varphi(jd)\sum_{k|(i,j)}\mu(k)=d=1min(n,m)?φ(d)d?i=1?dn???j=1?dm???φ(id)φ(jd)k(i,j)?μ(k)=∑d=1min?(n,m)dφ(d)∑k=1min?(?nd?,?md?)μ(k)∑i=1?ndk?φ(ikd)∑j=1?mdk?φ(jkd)=\sum_{d=1}^{\min(n,m)}\fracozvdkddzhkzd{\varphi(d)}\sum_{k=1}^{\min(\lfloor\frac nd\rfloor,\lfloor\frac m d\rfloor)}\mu(k)\sum_{i=1}^{\lfloor\frac{n}{dk}\rfloor}\varphi(ikd)\sum_{j=1}^{\lfloor\frac{m}{dk}\rfloor}\varphi(jkd)=d=1min(n,m)?φ(d)d?k=1min(?dn??,?dm??)?μ(k)i=1?dkn???φ(ikd)j=1?dkm???φ(jkd)∥t=dk?k=td\Bigg\lVert{t=dk\Leftrightarrow k=\frac{t}ozvdkddzhkzd}?t=dk?k=dt?=∑t=1min?(n,m)∑d∣tdφ(d)μ(td)+∑i=1?nt?φ(it)∑j=1?mt?φ(jt)=\sum_{t=1}^{\min(n,m)}\sum_{d|t}\fracozvdkddzhkzd{\varphi(d)}\mu(\frac td)+\sum_{i=1}^{\lfloor\frac nt\rfloor}\varphi(it)\sum_{j=1}^{\lfloor\frac mt\rfloor}\varphi(jt) =t=1min(n,m)?dt?φ(d)d?μ(dt?)+i=1?tn???φ(it)j=1?tm???φ(jt)

f(t)=∑d∣tdφ(d)μ(td)f(t)=\sum_{d|t}\fracozvdkddzhkzd{\varphi(d)}\mu(\frac td)f(t)=dt?φ(d)d?μ(dt?),在 O(nlog?n)O(n\log n)O(nlogn) 的時間內預處理。

g(a,b)=∑i=1bφ(i?a)g(a,b)=\sum_{i=1}^b\varphi(i·a)g(a,b)=i=1b?φ(i?a)
∑i=1n∑j=1mφ(ij)?∑i=1min?(n,m)f(i)?g(i,?ni?)?g(i,?mi?)\sum_{i=1}^n\sum_{j=1}^m\varphi(ij)\Leftrightarrow \sum_{i=1}^{\min(n,m)}f(i)·g(i,\lfloor\frac ni\rfloor)·g(i,\lfloor\frac mi\rfloor) i=1n?j=1m?φ(ij)?i=1min(n,m)?f(i)?g(i,?in??)?g(i,?im??)注意到有用的 g(a,b)g(a,b)g(a,b) 均滿足 ab≤max?(n,m)ab\le \max(n,m)abmax(n,m),可以用動態二維數組預處理。

根據定義容易得遞推式 :g(a,b)=g(a,b?1)+φ(ab):g(a,b)=g(a,b-1)+\varphi(ab):g(a,b)=g(a,b?1)+φ(ab)

設前綴和 s(x,y,n)=∑i=1nf(i)g(i,x)g(i,y)s(x,y,n)=\sum_{i=1}^nf(i)g(i,x)g(i,y)s(x,y,n)=i=1n?f(i)g(i,x)g(i,y),則有遞推式 s(x,y,n)=s(x,y,n?1)+f(n)g(n,x)g(n,y)s(x,y,n)=s(x,y,n-1)+f(n)g(n,x)g(n,y)s(x,y,n)=s(x,y,n?1)+f(n)g(n,x)g(n,y)

設定一個閾值 BBB,預處理所有 x≤B∧y≤Bx\le B\wedge y\le BxByBs(x,y,z)s(x,y,z)s(x,y,z),此時還滿足 z≤nmax?(x,y)z\le \frac{n}{\max(x,y)}zmax(x,y)n?,同理用動態三維數組存。

詢問時枚舉 iii
對于 ?ni?≤B∧?mi?≤B\lfloor\frac n i\rfloor\le B\wedge\lfloor\frac m i\rfloor\le B?in??B?im??B 直接暴力求 f(i)g(i,?ni?)g(i,?mi?)f(i)g(i,\lfloor\frac ni\rfloor)g(i,\lfloor\frac m i\rfloor)f(i)g(i,?in??)g(i,?im??)(反正都是預處理過的信息)。

其余部分利用預處理的前綴和 s(x,y,z)s(x,y,z)s(x,y,z) 直接整除分塊計算。

假設當 i∈[l,r]i\in[l,r]i[l,r] 時,?ni?,?mi?\lfloor\frac n i\rfloor,\lfloor\frac m i\rfloor?in??,?im?? 均相同,即 f(i)g(i,?ni?)g(i,?mi?)f(i)g(i,\lfloor\frac n i\rfloor)g(i,\lfloor\frac m i\rfloor)f(i)g(i,?in??)g(i,?im??) 相同,

∑i=lrf(i)g(i,x)g(i,y)=s(x,y,r)?s(x,y,l?1)\sum_{i=l}^rf(i)g(i,x)g(i,y)=s(x,y,r)-s(x,y,l-1)i=lr?f(i)g(i,x)g(i,y)=s(x,y,r)?s(x,y,l?1)

查詢時間復雜度 O(TnB+Tn)O(T\frac nB+T\sqrt{n})O(TBn?+Tn?),預處理時間 O(nlog?n+nB)O(n\log n+nB)O(nlogn+nB),空間復雜度 O(nB)O(nB)O(nB)

B=n13B=n^{\frac 1 3}B=n31? 時復雜度較優秀。

code

#include <bits/stdc++.h> using namespace std; #define int long long #define mod 998244353 #define maxn 100005 #define maxB 60 int *g[maxn], *s[maxB][maxB]; int mu[maxn], phi[maxn], prime[maxn], f[maxn]; bool vis[maxn]; int cnt;int qkpow( int x, int y ) {int ans = 1;while( y ) {if( y & 1 ) ans = ans * x % mod;x = x * x % mod;y >>= 1;}return ans; }void sieve( int n = 1e5, int B = 50 ) {mu[1] = phi[1] = 1;for( int i = 2;i <= n;i ++ ) {if( ! vis[i] ) {prime[++ cnt] = i;phi[i] = i - 1;mu[i] = -1;}for( int j = 1;j <= cnt and i * prime[j] <= n;j ++ ) {vis[i * prime[j]] = 1;if( i % prime[j] == 0 ) {mu[i * prime[j]] = 0;phi[i * prime[j]] = phi[i] * prime[j] % mod;break;}else {mu[i * prime[j]] = -mu[i];phi[i * prime[j]] = phi[i] * phi[prime[j]] % mod;}}}for( int i = 1;i <= n;i ++ )for( int j = i;j <= n;j += i )( f[j] += i * qkpow( phi[i], mod - 2 ) % mod * mu[j / i] ) %= mod;for( int i = 1;i <= n;i ++ ) {g[i] = new int [n / i + 5];g[i][0] = 0;for( int j = 1;i * j <= n;j ++ )g[i][j] = ( g[i][j - 1] + phi[i * j] ) % mod;}for( int i = 1;i <= B;i ++ )for( int j = 1;j <= B;j ++ ) {s[i][j] = new int [n / max( i, j ) + 5];s[i][j][0] = 0;for( int k = 1;k * max( i, j ) <= n;k ++ )s[i][j][k] = ( s[i][j][k - 1] + f[k] * g[k][i] % mod * g[k][j] ) % mod;} }signed main() {sieve();int T, n, m, B = 50;scanf( "%lld", &T );while( T -- ) {scanf( "%lld %lld", &n, &m );if( n > m ) swap( n, m );int ans = 0;for( int i = 1;i <= m / B;i ++ )( ans += f[i] * g[i][n / i] % mod * g[i][m / i] ) %= mod;for( int l = m / B + 1, r;l <= n;l = r + 1 ) {r = min( n / ( n / l ), m / ( m / l ) );( ans += s[n / l][m / l][r] - s[n / l][m / l][l - 1] ) %= mod;}printf( "%lld\n", ( ans + mod ) % mod );}return 0; }

總結

以上是生活随笔為你收集整理的luogu P4240 毒瘤之神的考验(莫比乌斯反演+递推前缀和+数论分块)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。