SP8099 TABLE - Crash´s number table 题解

题目传送门

前置知识

一般的积性函数 | 数论分块 | 莫比乌斯反演

解法

nm

考虑莫比乌斯反演,推式子,有 i=1nj=1nlcm(i,j)=i=1nj=1nijgcd(i,j)=k=1n1ki=1nj=1nij[gcd(i,j)=k]=k=1n1ki=1nkj=1mkijk2[gcd(i,j)=1]=k=1nki=1nkj=1mkijd|gcd(i,j)μ(d)=k=1nkd=1nμ(d)i=1nkj=1mkij[d|gcd(i,j)]=k=1nkd=1nμ(d)d2i=1nkdj=1mkdij=k=1nkd=1nμ(d)d2i=1nkdij=1mkdj=T=1nTd|Tμ(d)di=1nTij=1mTj

f(n)=d|nμ(d)d 显然是积性函数,线筛筛一下即可。

接着维护前缀和后整除分块。

需要注意的是本题仅限 C++98 提交。

代码

#include<bits/stdc++.h>
using namespace std;
#define ll long long 
#define ull unsigned long long
#define sort stable_sort 
#define endl '\n'
const ll p=20101009;
ll prime[10000010],f[10000010],s[10000010],len=0;
bool vis[10000010];
void isprime(ll n)
{
	memset(vis,0,sizeof(vis));
	f[1]=1;
	for(ll i=2;i<=n;i++)
	{
		if(vis[i]==0)
		{
			len++;
			prime[len]=i;
			f[i]=1-i;
		}
		for(ll j=1;j<=len&&i*prime[j]<=n;j++)
		{
			vis[i*prime[j]]=1;
			if(i%prime[j]==0)
			{
				f[i*prime[j]]=f[i];
				break;
			}
			else
			{
				f[i*prime[j]]=f[i]*f[prime[j]];
			}
		}
	}
	for(ll i=1;i<=n;i++)
	{
		s[i]=(s[i-1]+i)%p;
		f[i]=(f[i-1]+f[i]*i%p+p)%p;
	}
}
ll ask(ll n,ll m)
{
	ll ans=0,l,r;
	for(l=1,r;l<=n;l=r+1)
	{
		r=min(n/(n/l),m/(m/l));
		ans=(ans+(s[n/l]*s[m/l]%p)*(f[r]-f[l-1]+p)%p)%p;
	}
	return ans;
}
int main()
{
	ll n,m;
	cin>>n>>m;
	isprime(max(n,m));
	if(n>m)
	{
		swap(n,m);
	}
	cout<<ask(n,m)<<endl;
	return 0;
}

后记

多倍经验:luogu P1829 [国家集训队] Crash的数字表格 / JZPTAB

posted @   hzoi_Shadow  阅读(18)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
扩大
缩小
点击右上角即可分享
微信分享提示