21.6.23 t1
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}\) 会爆long long。
#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;
}