void init()
{
mu[1]=1;
for(int i = 2; i<maxn; i++)
{
if(vis[i]==0)
{
vis[i]=1;
pri[cnt++]=i;
mu[i]=-1;
}
for(int j=0; j<cnt; j++)
{
if(1ll*pri[j]*i>=maxn)
break;
vis[i*pri[j]]=1;
if(i%pri[j]==0)
{
mu[i*pri[j]]=0;
break;
}
else
mu[i*pri[j]]=-mu[i];
}
}
}
两种表达形式和性质(个人感觉形式2也就是倍数形式比较常用?)
反演经常用到一个性质叫整除分块
for(int l=1,r;l<=n;l=r+1)
{
r=n/(n/l);
ans+=(r-l+1)*(n/l);
}
入门题,注意需要分块不然会T
#include
using namespace std;
typedef long long ll;
const int maxn=50005;
ll mu[maxn],sum[maxn];
ll pri[maxn];
ll cnt=0;
bool vis[maxn];
void init()
{
vis[0]=vis[1]=1;
mu[1]=1;
sum[1]=1;
for(int i = 2;i<maxn;i++)
{
if(vis[i]==0)
{
vis[i]=1;
pri[cnt++]=i;
mu[i]=-1;
}
for(int j=0;j<cnt;j++)
{
if(pri[j]*i>=maxn) break;
vis[i*pri[j]]=1;
if(i%pri[j]==0)
{
mu[i*pri[j]]=0;
break;
}
else mu[i*pri[j]]=-mu[i];
}
}
for(int i=1;i<maxn;i++) sum[i]=sum[i-1]+mu[i];
}
ll a,b,d,t,n;
int main()
{
ios::sync_with_stdio(0);
init();
cin>>t;
while(t--)
{
cin>>a>>b>>d;
a/=d;b/=d;
ll ans=0;
for(ll i =1,r;i<=min(a,b);i=r+1)
{
r=min(a/(a/i),b/(b/i));
ans+=(a/i)*(b/i)*(sum[r]-sum[i-1]);
}
cout<<ans<<endl;
}
return 0;
}
另f(x)为gcd(i,j)==x 时这个函数的值 F(x)就是gcd(i,j)==d的倍数时这个函数的值
不难发现gcd(i,j)==d的倍数 那么 i,j都是d的倍数,那么最小的i就是d 就最大i就是 ⌊ m i ⌋ \left\lfloor\frac{m}{i}\right\rfloor ⌊im⌋*i 一共有 ⌊ m i ⌋ \left\lfloor\frac{m}{i}\right\rfloor ⌊im⌋个,等差数列求和(a1+an)n/2 得到(i+ ⌊ m i ⌋ \left\lfloor\frac{m}{i}\right\rfloor ⌊im⌋i) ∗ ⌊ m i ⌋ *\left\lfloor\frac{m}{i}\right\rfloor ∗⌊im⌋/2 提出公因式i并且约掉分母可以得到 (1+ ⌊ m i ⌋ \left\lfloor\frac{m}{i}\right\rfloor ⌊im⌋) ⌊ m i ⌋ \left\lfloor\frac{m}{i}\right\rfloor ⌊im⌋i
同理 j就是(1+ ⌊ n i ⌋ \left\lfloor\frac{n}{i}\right\rfloor ⌊in⌋) ⌊ n i ⌋ \left\lfloor\frac{n}{i}\right\rfloor ⌊in⌋i
同理,直接循环会t对mu[i]*i^2 求前缀和
#include
using namespace std;
typedef long long ll;
const long long mod=998244353LL;
const int maxn=1e7+5;
int mu[maxn];
ll sum[maxn];
int pri[maxn];
int cnt=0;
bool vis[maxn];
void init()
{
vis[0]=vis[1]=1;
mu[1]=1;
sum[0]=0;
for(int i = 2;i<maxn;i++)
{
if(vis[i]==0)
{
vis[i]=1;
pri[cnt++]=i;
mu[i]=-1;
}
for(int j=0;j<cnt;j++)
{
if(1ll*pri[j]*i>=maxn) break;
vis[i*pri[j]]=1;
if(i%pri[j]==0)
{
mu[i*pri[j]]=0;
break;
}
else mu[i*pri[j]]=-mu[i];
}
}
for(ll i=1;i<maxn;i++) sum[i]=(sum[i-1]+mu[i]*i*i)%mod;
}
ll n,m,t;
int main()
{
ios::sync_with_stdio(0);
init();
cin>>t;
while(t--)
{
cin>>n>>m;
ll ans=0;
for(ll i =1,r;i<=min(n,m);i=r+1)
{
r=min(m/(m/i),n/(n/i));
ll m1=(m/i)%mod,n1=(n/i)%mod;
ans=((((((((((1+m1))%mod*m1)%mod*(1+(n1)))%mod*n1)%mod*1)%mod*1)%mod*ll(sum[r]-sum[i-1])%mod))%mod+ans)%mod;
// cout<
}
cout<<((2*ans)%mod+mod)%mod<<endl;
}
return 0;
}