21.6.23 t1
阿新 • • 發佈:2021-06-24
tag:數論,杜教篩,類歐函式,莫比烏斯反演
改一下,求 \(\frac ij\le \frac ab\)。
先莫反一下,方便求。
\[\sum_{gcd(i,j)=1}\frac ij\le\frac ab \]\[\sum_{d}\mu(d)\sum_{i=1}^{\left\lfloor\frac nd\right\rfloor}\sum_{j=1}^{\left\lfloor\frac nd\right\rfloor}\frac ij\le\frac ab \]數論分塊,\(\mu\) 的字首和是杜教篩模板,後面一堆是類歐函式模板第一問。
注意一個坑點, \(10^{10}\times10^{10}\)
#include<bits/stdc++.h> using namespace std; template<typename T> inline void Read(T &n){ char ch; bool flag=false; while(!isdigit(ch=getchar()))if(ch=='-')flag=true; for(n=ch^48;isdigit(ch=getchar());n=(n<<1)+(n<<3)+(ch^48)); if(flag)n=-n; } typedef long long ll; enum{ MOD = 998244353, MAXN = 10000005, inv2 = MOD+1>>1 }; inline int inc(int a, int b){ a += b; if(a>=MOD) a -= MOD; return a; } inline int dec(int a, int b){ a -= b; if(a<0) a += MOD; return a; } inline void iinc(int &a, int b){a = inc(a,b);} inline void ddec(int &a, int b){a = dec(a,b);} inline void upd(int &a, ll b){a = (a+b)%MOD;} namespace pts30{ int gcd(int a, int b){return b?gcd(b,a%b):a;} inline int solve(int a, int b, int c, int d, int n){ int ans=0; for(int i=1; i<=n; i++) for(int j=(1ll*a*i+b-1)/b; j<=1ll*c*i/d; j++) if(gcd(i,j)==1) ans++; return ans%MOD; } } char check[MAXN]; int mu[MAXN], prime[MAXN], pnum; inline void sieve(){ mu[1] = 1; for(int i=2; i<MAXN; i++){ if(!check[i]) prime[++pnum] = i, mu[i] = -1; for(int j=1; i*prime[j]<MAXN and j<=pnum; j++){ check[i*prime[j]] = true; if(i%prime[j]==0) break; mu[i*prime[j]] = -mu[i]; } } for(int i=1; i<MAXN; i++){ if(mu[i]==-1) mu[i] = MOD-1; iinc(mu[i],mu[i-1]); } } int count(ll a, ll b, ll c, ll n){ if(a==0) return (n+1)%MOD*(b/c)%MOD; if(a>=c or b>=c) return (n%MOD*(n+1)%MOD*inv2%MOD*(a/c)+(n+1)%MOD*(b/c)+count(a%c,b%c,c,n))%MOD; ll m = (n*a+b)/c; return dec(n%MOD*m%MOD,count(c,c-b-1,a,m-1)); } namespace Sieve{ ll n, M; inline int id(ll x){return x<=M ? x : M+n/x;} char vis[MAXN<<1]; int smu[MAXN<<1]; int get_mu(ll x){ if(x<MAXN) return mu[x]; if(vis[id(x)]) return smu[id(x)]; vis[id(x)] = true; int res=1; for(register ll l=2, r=0; l<=x; l=r+1){ r = x/(x/l); ddec(res,(r-l+1)*get_mu(x/l)%MOD); } return smu[id(x)] = res; } } inline int summu(ll l, ll r){ // return dec(mu[r],mu[l-1]); return dec(Sieve::get_mu(r),Sieve::get_mu(l-1)); } inline int calc(int a, int b, ll n){ int ans=0; for(ll l=1, r; l<=n; l=r+1){ r = n/(n/l); upd(ans,1ll*summu(l,r)*count(a,0,b,n/l)); } return ans; } inline int solve(int a, int b, int c, int d, ll n){return inc(dec(calc(c,d,n),calc(a,b,n)),d<=n);} int main(){ int T; Read(T); sieve(); while(T--){ ll n; int a, b, c, d; Read(n); Read(a); Read(b); Read(c); Read(d); Sieve::n = n; memset(Sieve::vis,0,sizeof Sieve::vis); Sieve::M = sqrt(n); // cout<<pts30::solve(a,b,c,d,n)<<'\n'; cout<<solve(a,b,c,d,n)<<'\n'; } return 0; }