标签:algorithm code math line min ++ har name pre
莫比乌斯反演神仙题,写之前就知道是神仙题,但不想放弃,坚持下来学别人怎么写学了两天,收获巨大!!!
#include <cstdio> #include <cmath> #include <algorithm> using namespace std; #define ll long long #define re register const int p=998244353; const int B=35; const int N=1e5+10; const int M=1e5; void read(int &a) { int d=1; a=0; char ch; while(ch=getchar(),ch>‘9‘||ch<‘0‘) if(ch==‘-‘) d=-1; a=ch^48; while(ch=getchar(),ch>=‘0‘&&ch<=‘9‘) a=(a<<3)+(a<<1)+(ch^48); a*=d; } int phi[N],mu[N],pri[N],cnt,inv[N]; ll *G[N],F[N],*S[B+1][B+1]; bool vis[N]; inline void init() { inv[1]=phi[1]=mu[1]=1; for(re int i=2;i<=M;i++) { if(!vis[i]) pri[++cnt]=i,mu[i]=-1,phi[i]=i-1; for(re int j=1;j<=cnt&&i*pri[j]<=M;j++) { vis[i*pri[j]]=1; if(i%pri[j]==0) { phi[i*pri[j]]=phi[i]*pri[j]; break; } mu[i*pri[j]]=-mu[i]; phi[i*pri[j]]=phi[i]*(pri[j]-1); } } for(re int i=2;i<=M;i++) inv[i]=1ll*(p-p/i)*inv[p%i]%p; for(re int i=1;i<=M;i++)///枚举因子 (nlogn筛出F[x]) for(re int j=1;j*i<=M;j++) F[i*j]=(F[i*j]+1ll*(i*mu[j]%p)*inv[phi[i]]%p)%p; for(re int i=1;i<=M;i++) { G[i]=new ll [M/i+1]; G[i][0]=0; for(re int j=1;j<=M/i;j++) G[i][j]=(G[i][j-1]+phi[i*j]); } for(re int j=1;j<=B;j++) for(re int k=1;k<=B;k++) { ll len=M/max(j,k); S[j][k]=new ll [len+1]; S[j][k][0]=0; for(re int i=1;i<=len;i++) S[j][k][i]=(S[j][k][i-1]+(F[i]*G[i][j])%p*G[i][k]%p)%p; } } inline ll solve(int n,int m) { if(n>m) swap(n,m); ll ans=0; for(re int i=1;i<=m/B;i++) ans=(ans+(F[i]*G[i][n/i]%p)*G[i][m/i]%p)%p; for(int l=m/B+1,r;l<=n;l=r+1) { r=min(n/(n/l),m/(m/l)); ans=(ans+(S[n/l][m/l][r]-S[n/l][m/l][l-1]+p)%p)%p; } return ans; } int main() { init(); int T; read(T); while(T--) { int n,m; read(n); read(m); printf("%lld\n",solve(n,m)); } return 0; }
标签:algorithm code math line min ++ har name pre
原文地址:https://www.cnblogs.com/acm1ruoji/p/10831567.html