@ivorysi
2018-01-05T00:27:19.000000Z
字数 19877
阅读 1504
笔记
对于互质的两个数a,b,f(ab)=f(a)*f(b)
对于任意两个数,f(ab)=f(a)f(b)
欧拉函数表示[1,n]中与n互质的数,
欧拉函数是积性函数,但不是完全积性函数
有一些特殊的小性质
[1,n]中与n互质的数的和是
因为互质的数总是成对出现,例如k和n互质,n-k必然也和n互质,否则k不与n互质
如果n有平方数因子的话
如果n有k个质因子的话
如果n=1的话
表示n的所有正因子k次幂之和
表示n的所有正因子之和
其余时候全是0
这个式子可以用容斥来考虑
1的时候式子是n,然后对于的一个质因子,我们筛去所有个,也就是p的倍数,但是会重复筛掉一些数,如果有那么这个d就被删掉了两次,我们就加回来,如果有它被减去了3次,又被恢复了3次,然后再减去它……所以就得到了这个式子
设n中有k个不同的质因子
考虑杨辉三角,组合数之间分别填上+号和-号,最后的和一定是0
只有当n=1的时候,这个式子的值才是1
若有两个函数f,g
则他们也满足
它还有另一种形式
若两个函数满足
则
给出正整数n和k,计算j(n, k)=k mod 1 + k mod 2 + k mod 3 + … + k mod n的值,其中k mod i表示k除以i的余数。例如j(5, 3)=3 mod 1 + 3 mod 2 + 3 mod 3 + 3 mod 4 + 3 mod 5=0+1+0+3+3=7
输入仅一行,包含两个整数n, k。
输出仅一行,即j(n, k)。
5 3
7
50%的数据满足:1<=n, k<=1000 100%的数据满足:1<=n ,k<=10^9
可以拆式子
而取值只有个
因为如果,那么有种不同取值,时,取值只能在以内,那么值只有
#include <iostream>#include <cstdio>#include <algorithm>#include <cstring>#include <vector>#include <cmath>#define siji(i,x,y) for(int i=(x);i<=(y);++i)#define gongzi(j,x,y) for(int j=(x);j>=(y);--j)#define xiaosiji(i,x,y) for(int i=(x);i<(y);++i)//#define ivorysiusing namespace std;typedef long long ll;int n,k;ll ans;int main() {#ifdef ivorysifreopen("f1.in","r",stdin);#endifscanf("%d%d",&n,&k);if(n>k) {ans=(ll)(n-k)*k;n=k;}int t,r;for(int i=1;i<=n;i=r+1) {t=k/i;r=k/t;if(r>n) r=n;ans+=(ll)(r-i+1)*k-(ll)(r-i+1)*(i+r)/2*t;}printf("%lld\n",ans);return 0;}
Longge的数学成绩非常好,并且他非常乐于挑战高难度的数学问题。现在问题来了:给定一个整数N,你需要求出∑gcd(i, N)(1<=i <=N)。
一个整数,为N。
一个整数,为所求的答案。
6
15
【数据范围】
对于60%的数据,0 对于100%的数据,0
如何快速求出这个
我们枚举每个质因子有几个就好了,可以dfs
#include <iostream>#include <cstdio>#include <algorithm>#include <cstring>#include <vector>#include <cmath>#define siji(i,x,y) for(int i=(x);i<=(y);++i)#define gongzi(j,x,y) for(int j=(x);j>=(y);--j)#define xiaosiji(i,x,y) for(int i=(x);i<(y);++i)#define MAXN 1000005//#define ivorysiusing namespace std;typedef long long ll;ll n;ll ans;ll prime[MAXN];int cnt[MAXN],tot;void dfs(int dep,ll now,ll eu) {if(dep>tot) {ans+=(n/now)*eu;return;}dfs(dep+1,now,eu);ll t=1;siji(i,1,cnt[dep]) {t=t*prime[dep];dfs(dep+1,now*t,eu*t/prime[dep]*(prime[dep]-1));}}int main() {#ifdef ivorysifreopen("f1.in","r",stdin);#endifscanf("%lld",&n);int t=n;for(int i=2;i<=t/i;++i) {if(t%i==0) {prime[++tot]=i;while(t%i==0) {++cnt[tot];t/=i;}}}if(t!=1) {prime[++tot]=t;cnt[tot]=1;}dfs(1,1,1);printf("%lld\n",ans);return 0;}
Given n, calculate the sum LCM(1,n) + LCM(2,n) + .. + LCM(n,n), where LCM(i,n) denotes the Least Common Multiple of the integers i and n.
The first line contains T the number of test cases. Each of the next T lines contain an integer n.
Output T lines, one for each test case, containing the required sum.
3
1
2
5
1
4
55
Constraints
1 <= T <= 300000
1 <= n <= 1000000
除法比乘法慢了那么多!!!
这道题卡常!!!
我们预处理每个数的与它互质且比它小的数的和,然后对于每个n枚举约数
拼命卡常啊QAQ
#include <iostream>#include <cstdio>#include <algorithm>#include <cstring>#include <vector>#include <cmath>#define siji(i,x,y) for(int i=(x);i<=(y);++i)#define gongzi(j,x,y) for(int j=(x);j>=(y);--j)#define xiaosiji(i,x,y) for(int i=(x);i<(y);++i)#define MAXN 1000005//#define ivorysiusing namespace std;typedef long long ll;ll phi[MAXN*2];bool nonprime[MAXN*2];int prime[MAXN*2],tot;int T,n;ll ans;int read() {char c=getchar();int res=0;while(c<'0' || c>'9') c=getchar();while(c>='0' && c<='9') {res=res*10+c-'0';c=getchar();}return res;}void out(ll x) {if(x>=10) {out(x/10);}putchar('0'+x%10);}int main() {#ifdef ivorysifreopen("f1.in","r",stdin);#endifphi[1]=1;siji(i,2,1000000) {if(!nonprime[i]) {phi[i]=i-1;prime[++tot]=i;}siji(j,1,tot) {if((ll)prime[j]*i>1000000) break;nonprime[i*prime[j]]=1;if(i%prime[j]==0) {phi[i*prime[j]]=phi[i]*prime[j];break;}phi[i*prime[j]]=phi[i]*(prime[j]-1);}}siji(i,2,1000000) phi[i]=phi[i]*i/2;T=read();while(T--) {n=read();ans=0;for(int i=1;i*i<=n;++i) {if(n%i==0) {ans+=phi[i];if(i*i<n) {ans+=phi[n/i];}}}ans=ans*n;out(ans);putchar('\n');}return 0;}
FGD正在破解一段密码,他需要回答很多类似的问题:对于给定的整数a,b和d,有多少正整数对x,y,满足x<=a
,y<=b,并且gcd(x,y)=d。作为FGD的同学,FGD希望得到你的帮助。
第一行包含一个正整数n,表示一共有n组询问。(1<=n<= 50000)接下来n行,每行表示一个询问,每行三个
正整数,分别为a,b,d。(1<=d<=a,b<=50000)
对于每组询问,输出到输出文件zap.out一个正整数,表示满足条件的整数对数。
2
4 5 2
6 4 3
3
2
//对于第一组询问,满足条件的整数对有(2,2),(2,4),(4,2)。对于第二组询问,满足条件的整数对有(
6,3),(3,3)。
我们转化一下
求之间有多少个互质的数
以下还用表示区间左右端点
然后列出式子
然后因为只有种取值,且每段都对应一段连续的取值,然后这个东西的取值不超过
#include <iostream>#include <cstdio>#include <algorithm>#include <cstring>#include <vector>#include <cmath>#define siji(i,x,y) for(int i=(x);i<=(y);++i)#define gongzi(j,x,y) for(int j=(x);j>=(y);--j)#define xiaosiji(i,x,y) for(int i=(x);i<(y);++i)#define MAXN 1000005//#define ivorysiusing namespace std;typedef long long ll;const int N = 50000;int miu[N+10],prime[N+10],tot,sum[N+10],T;bool nonprime[N+10];ll ans=0;int main() {#ifdef ivorysifreopen("f1.in","r",stdin);#endifmiu[1]=1;siji(i,2,N) {if(!nonprime[i]) {prime[++tot]=i;miu[i]=-1;}siji(j,1,tot) {if(i*prime[j]>N) break;nonprime[i*prime[j]]=1;if(i%prime[j]==0) break;miu[i*prime[j]]=-miu[i];}}siji(i,1,N) {sum[i]=sum[i-1]+miu[i];}scanf("%d",&T);int a,b,d;while(T--) {scanf("%d%d%d",&a,&b,&d);a/=d;b/=d;ans=0;int n=min(a,b);int r;for(int i=1;i<=n;i=r+1) {r=min(a/(a/i),b/(b/i));if(r>n) r=n;ans+=(ll)(a/i)*(b/i)*(sum[r]-sum[i-1]);}printf("%lld\n",ans);}return 0;}
小 X 自幼就很喜欢数。但奇怪的是,他十分讨厌完全平方数。他觉得这些
数看起来很令人难受。由此,他也讨厌所有是完全平方数的正整数倍的数。然而
这丝毫不影响他对其他数的热爱。
这天是小X的生日,小 W 想送一个数给他作为生日礼物。当然他不能送一
个小X讨厌的数。他列出了所有小X不讨厌的数,然后选取了第 K个数送给了
小X。小X很开心地收下了。
然而现在小 W 却记不起送给小X的是哪个数了。你能帮他一下吗?
包含多组测试数据。文件第一行有一个整数 T,表示测试
数据的组数。
第2 至第T+1 行每行有一个整数Ki,描述一组数据,含义如题目中所描述。
含T 行,分别对每组数据作出回答。第 i 行输出相应的
第Ki 个不是完全平方数的正整数倍的数。
4
1
13
100
1234567
1
19
163
2030745
对于 100%的数据有 1 ≤ Ki ≤ 10^9,T ≤ 50
这道题考虑容斥原理,和的性质
二分一个x,考虑快速之间有多少个非完全平方数的个数
这个就相当于,1的倍数,减去1个质数平方的倍数,加上2个质数平方的倍数……
发现这个东西符号刚好和的正负一样
#include <iostream>#include <cstdio>#include <algorithm>#include <cstring>#include <vector>#include <cmath>#define siji(i,x,y) for(int i=(x);i<=(y);++i)#define gongzi(j,x,y) for(int j=(x);j>=(y);--j)#define xiaosiji(i,x,y) for(int i=(x);i<(y);++i)#define MAXN 1000005//#define ivorysiusing namespace std;typedef long long ll;const int N = 100000;int miu[N+10],prime[N+10],tot,sum[N+10],T;bool nonprime[N+10];ll ans=0;ll check(ll mid) {ll res=0;for(ll i=1;i*i<=mid;++i) {if(miu[i]==0) continue;res+=(ll)miu[i]*(mid/(i*i));}return res;}int main() {#ifdef ivorysifreopen("f1.in","r",stdin);#endifmiu[1]=1;siji(i,2,N) {if(!nonprime[i]) {prime[++tot]=i;miu[i]=-1;}siji(j,1,tot) {if(i*prime[j]>N) break;nonprime[i*prime[j]]=1;if(i%prime[j]==0) break;miu[i*prime[j]]=-miu[i];}}scanf("%d",&T);ll k;while(T--) {scanf("%lld",&k);ll l=1,r=10000000000LL;while(l<r) {ll mid=(l+r)>>1;if(check(mid)>=k) r=mid;else l=mid+1;}printf("%lld\n",r);}return 0;}
神犇YY虐完数论后给傻×kAc出了一题给定N, M,求1<=x<=N, 1<=y<=M且gcd(x, y)为质数的(x, y)有多少对kAc这种
傻×必然不会了,于是向你来请教……多组输入
第一行一个整数T 表述数据组数接下来T行,每行两个正整数,表示N, M
T行,每行一个整数表示第i组数据的结果
2
10 10
100 100
30
2791
T = 10000
N, M <= 10000000
这道题按照之前某道1101的思路,可以很容易想到一个超时思路
枚举一个质数
然后我们可以设
我们只要能求出对于然后处理成前缀和就很妙了,就变成1101了
然后我们枚举每个质数,去更新它的倍数的话,根据调和级数,均摊是的
然后质数一共有个所以复杂度是可以暴力预处理
#include <iostream>#include <cstdio>#include <algorithm>#include <cstring>#include <vector>#include <cmath>#define siji(i,x,y) for(int i=(x);i<=(y);++i)#define gongzi(j,x,y) for(int j=(x);j>=(y);--j)#define xiaosiji(i,x,y) for(int i=(x);i<(y);++i)#define MAXN 10000005//#define ivorysiusing namespace std;typedef long long ll;ll sum[MAXN];bool nonprime[MAXN];int prime[MAXN],tot,n,m,miu[MAXN];int main() {#ifdef ivorysifreopen("f1.in","r",stdin);#endifmiu[1]=1;siji(i,2,10000000) {if(!nonprime[i]) {prime[++tot]=i;miu[i]=-1;}siji(j,1,tot) {if(i>10000000/prime[j]) break;nonprime[i*prime[j]]=1;if(i%prime[j]==0) break;miu[i*prime[j]]=-miu[i];}}siji(i,1,tot) {int t=prime[i];while(t<=10000000) sum[t]+=miu[t/prime[i]],t+=prime[i];}siji(i,1,10000000) sum[i]+=sum[i-1];int T;scanf("%d",&T);while(T--) {scanf("%d%d",&n,&m);int t=min(n,m),r;ll ans=0;for(int i=1;i<=t;i=r+1) {r=min(n/(n/i),m/(m/i));if(r>t) r=t;ans+=(ll)(sum[r]-sum[i-1])*(n/i)*(m/i);}printf("%lld\n",ans);}return 0;}
栋栋有一块长方形的地,他在地上种了一种能量植物,这种植物可以采集太阳光的能量。在这些植物采集能量后,
栋栋再使用一个能量汇集机器把这些植物采集到的能量汇集到一起。 栋栋的植物种得非常整齐,一共有n列,每列
有m棵,植物的横竖间距都一样,因此对于每一棵植物,栋栋可以用一个坐标(x, y)来表示,其中x的范围是1至n,
表示是在第x列,y的范围是1至m,表示是在第x列的第y棵。 由于能量汇集机器较大,不便移动,栋栋将它放在了
一个角上,坐标正好是(0, 0)。 能量汇集机器在汇集的过程中有一定的能量损失。如果一棵植物与能量汇集机器
连接而成的线段上有k棵植物,则能量的损失为2k + 1。例如,当能量汇集机器收集坐标为(2, 4)的植物时,由于
连接线段上存在一棵植物(1, 2),会产生3的能量损失。注意,如果一棵植物与能量汇集机器连接的线段上没有植
物,则能量损失为1。现在要计算总的能量损失。 下面给出了一个能量采集的例子,其中n = 5,m = 4,一共有20
棵植物,在每棵植物上标明了能量汇集机器收集它的能量时产生的能量损失。 在这个例子中,总共产生了36的能
量损失。
仅包含一行,为两个整数n和m。
仅包含一个整数,表示总共产生的能量损失。
5 4
3 4
36
20
对于100%的数据:1 ≤ n, m ≤ 100,000。
这道题只要想起来某个公式,还是很简单的
这个公式就是
这个东西可以通过数学归纳法证明,就是证明如果n是一个质数的指数幂,然后n是两个质数的指数幂……就证出来了
然后我们可以列式子
然后我们发现最难算的是这个(废话)
这道题就愉快的出解了
#include <iostream>#include <cstdio>#include <algorithm>#include <cstring>#include <vector>#include <cmath>#define siji(i,x,y) for(int i=(x);i<=(y);++i)#define gongzi(j,x,y) for(int j=(x);j>=(y);--j)#define xiaosiji(i,x,y) for(int i=(x);i<(y);++i)#define MAXN 100005//#define ivorysiusing namespace std;typedef long long ll;ll sum[MAXN];bool nonprime[MAXN];int prime[MAXN],tot,n,m,phi[MAXN];int main() {#ifdef ivorysifreopen("f1.in","r",stdin);#endifphi[1]=1;siji(i,2,100000) {if(!nonprime[i]) {prime[++tot]=i;phi[i]=i-1;}siji(j,1,tot) {if(i>100000/prime[j]) break;nonprime[i*prime[j]]=1;if(i%prime[j]==0) {phi[i*prime[j]]=phi[i]*prime[j];break;}phi[i*prime[j]]=phi[i]*(prime[j]-1);}}siji(i,1,100000) phi[i]+=phi[i-1];scanf("%d%d",&n,&m);int t=min(n,m),r;ll ans=0;for(int i=1;i<=t;i=r+1) {r=min(n/(n/i),m/(m/i));if(r>t) r=t;ans+=(ll)(phi[r]-phi[i-1])*(n/i)*(m/i);}ans=ans*2;ans-=(ll)n*m;printf("%lld\n",ans);return 0;}
有一张N×m的数表,其第i行第j列(1 < =i < =礼,1 < =j < =m)的数值为
能同时整除i和j的所有自然数之和。给定a,计算数表中不大于a的数之和。
输入包含多组数据。
输入的第一行一个整数Q表示测试点内的数据组数,接下来Q行,每行三个整数n,m,a(|a| < =10^9)描述一组数据。
对每组数据,输出一行一个整数,表示答案模2^31的值。
2
4 4 3
10 10 5
20
148
1 < =N.m < =10^5 , 1 < =Q < =2×10^4
满足然后
我们可以这么算
设g(p)表示以p为最大公约数的对数有多少个
然后这个式子就可以改成
我们可以线性递推出
我们发现如果 那么约数和是
如果 那么约数和是
我们需要把维护成一个前缀和,就可以快速处理了
考虑到我们离线处理,把询问按a排序,把排序,然后不断加入并更新到i的倍数上,用树状数组维护前缀和
然后这个东西是的
每次询问是
总复杂度是
#include <iostream>#include <cstdio>#include <algorithm>#include <cmath>#define siji(i,x,y) for(int i=(x);i<=(y);++i)#define gongzi(j,x,y) for(int j=(x);j>=(y);--j)#define xiaosiji(i,x,y) for(int i=(x);i<(y);++i)#define MAXN 100005//#define ivorysiusing namespace std;typedef long long ll;const int mod=(1<<30)-1+(1<<30);const int N=100000;int Q;int g[N+5],prime[N+5],tot,miu[N+5],pos[N+5],ans[N+5],tr[N+5];int f[N+5];bool nonprime[N*2];struct node {int n,m,id,a;bool operator < (const node &rhs) const {return a<rhs.a;}}qry[N];bool cmp(int a,int b) {return f[a]<f[b];}int lowbit(int x) {return x&(-x);}void Insert(int pos,int x) {if(x==0) return;while(pos<=N) {tr[pos]+=x;pos+=lowbit(pos);}}int query(int pos) {int res=0;while(pos>0) {res+=tr[pos];pos-=lowbit(pos);}return res;}int _query(int l,int r) {return query(r)-query(l-1);}int main() {#ifdef ivorysifreopen("f1.in","r",stdin);#endifmiu[1]=1;f[1]=1;siji(i,2,N) {if(!nonprime[i]) {prime[++tot]=i;miu[i]=-1;f[i]=i+1;}siji(j,1,tot) {if(prime[j]>N/i) break;nonprime[i*prime[j]]=1;if(i%prime[j]==0) {f[i*prime[j]]=((ll)(f[i]-f[i/prime[j]])*prime[j]+f[i]);break;}miu[i*prime[j]]=-miu[i];f[i*prime[j]]=f[i]*prime[j]+f[i];}}siji(i,1,N) pos[i]=i;sort(pos+1,pos+N+1,cmp);scanf("%d",&Q);siji(i,1,Q) {scanf("%d%d%d",&qry[i].n,&qry[i].m,&qry[i].a);qry[i].id=i;}sort(qry+1,qry+Q+1);int now=1;siji(i,1,Q) {while(now<=N && f[pos[now]]<=qry[i].a) {int t=pos[now];while(t<=N) {Insert(t,(f[pos[now]]&mod)*miu[t/pos[now]]);t+=pos[now];}++now;}int t=min(qry[i].n,qry[i].m),r;for(int j=1;j<=t;j=r+1) {r=min(qry[i].n/(qry[i].n/j),qry[i].m/(qry[i].m/j));if(r>t) r=t;ans[qry[i].id]+=_query(j,r)*(qry[i].n/j)*(qry[i].m/j);}ans[qry[i].id]&=mod;}siji(i,1,Q) {printf("%d\n",ans[i]);}return 0;}
今天的数学课上,Crash小朋友学习了最小公倍数(Least Common Multiple)。对于两个正整数a和b,LCM(a, b)表示能同时被a和b整除的最小正整数。例如,LCM(6, 8) = 24。回到家后,Crash还在想着课上学的东西,为了研究最小公倍数,他画了一张N*M的表格。每个格子里写了一个数字,其中第i行第j列的那个格子里写着数为LCM(i, j)。一个4*5的表格如下: 1 2 3 4 5 2 2 6 4 10 3 6 3 12 15 4 4 12 4 20 看着这个表格,Crash想到了很多可以思考的问题。不过他最想解决的问题却是一个十分简单的问题:这个表格中所有数的和是多少。当N和M很大时,Crash就束手无策了,因此他找到了聪明的你用程序帮他解决这个问题。由于最终结果可能会很大,Crash只想知道表格里所有数的和mod 20101009的值。
输入的第一行包含两个正整数,分别表示N和M。
输出一个正整数,表示表格中所有数的和mod 20101009的值。
4 5
122
100%的数据满足N, M ≤ 10^7。
严谨认真的推一下式子
我们枚举约数,然后表示中互质的和
然后考虑怎么求
枚举是的,计算是的,总体是的,已经可以解决本题
#include <iostream>#include <cstdio>#include <algorithm>#include <cmath>#define siji(i,x,y) for(int i=(x);i<=(y);++i)#define gongzi(j,x,y) for(int j=(x);j>=(y);--j)#define xiaosiji(i,x,y) for(int i=(x);i<(y);++i)#define MAXN 100005#define mod 20101009//#define ivorysiusing namespace std;typedef long long ll;const int N=10000000;bool nonprime[N+5];int prime[N+5],tot,miu[N+5],n,m,ans;int sum(int x,int y) {return (1LL*x*(x+1)/2%mod*(1LL*y*(y+1)/2%mod))%mod;}int calc(int x,int y) {int t=min(x,y),r;int res=0;for(int i=1;i<=t;i=r+1) {r=min(x/(x/i),y/(y/i));if(r>t) r=t;res+=1LL*sum(x/i,y/i)*(miu[r]-miu[i-1])%mod;res=(res%mod+mod)%mod;}return res;}int main() {#ifdef ivorysifreopen("f1.in","r",stdin);#endifmiu[1]=1;siji(i,2,N) {if(!nonprime[i]) {prime[++tot]=i;miu[i]=-1;}siji(j,1,tot) {if(prime[j]>N/i) break;nonprime[i*prime[j]]=1;if(i%prime[j]==0) break;miu[i*prime[j]]=-miu[i];}}siji(i,1,N) miu[i]=1LL*i*i%mod*miu[i]%mod;siji(i,1,N) miu[i]+=miu[i-1],miu[i]%=mod;scanf("%d%d",&n,&m);int r,t=min(n,m);for(int i=1;i<=t;i=r+1) {r=min(n/(n/i),m/(m/i));if(r>t) r=t;ans+=calc(n/i,m/i)*(1LL*(i+r)*(r-i+1)/2%mod)%mod;ans%=mod;}ans=(ans%mod+mod)%mod;printf("%d\n",ans);return 0;}
()
一个正整数T表示数据组数
接下来T行 每行两个正整数 表示N、M
T行 每行一个整数 表示第i组数据的结果
1
4 5
122
T <= 10000
N, M<=10000000
我们可以优化一下上一个式子,让它可以满足多组询问
我们发现只要求出
的前缀和我们就可以在中完成一次询问
考虑到,积性函数的约数和还是积性函数
然后我们可以在线性筛的同时求出这个函数值
当的时候我们直接让这个函数值乘上即可,因为多出来的约数的贡献全是0,所以直接考虑中
#include <iostream>#include <cstdio>#include <algorithm>#include <cmath>#define siji(i,x,y) for(int i=(x);i<=(y);++i)#define gongzi(j,x,y) for(int j=(x);j>=(y);--j)#define xiaosiji(i,x,y) for(int i=(x);i<(y);++i)#define MAXN 100005#define mod 100000009//#define ivorysiusing namespace std;typedef long long ll;const int N=10000000;bool nonprime[N+5];int prime[N+5],tot,func[N+5],n,m,ans,T;int sum(int x,int y) {return (1LL*x*(x+1)/2%mod*(1LL*y*(y+1)/2%mod))%mod;}int main() {#ifdef ivorysifreopen("f1.in","r",stdin);#endiffunc[1]=1;siji(i,2,N) {if(!nonprime[i]) {prime[++tot]=i;func[i]=((i-1LL*i*i%mod)%mod+mod)%mod;}siji(j,1,tot) {if(prime[j]>N/i) break;nonprime[i*prime[j]]=1;if(i%prime[j]==0) {func[i*prime[j]]=1LL*prime[j]*func[i]%mod;break;}func[i*prime[j]]=1LL*func[prime[j]]*func[i]%mod;}}siji(i,1,N) func[i]+=func[i-1],func[i]%=mod;scanf("%d",&T);while(T--) {ans=0;scanf("%d%d",&n,&m);int t=min(n,m),r;for(int i=1;i<=t;i=r+1) {r=min(n/(n/i),m/(m/i));if(r>t) r=t;ans+=1LL*sum(n/i,m/i)*(func[r]-func[i-1])%mod;ans=(ans%mod+mod)%mod;}printf("%d\n",ans);}return 0;}
对于任意的>1的n gcd(a, b)不是n^2的倍数
也就是说gcd(a, b)没有一个因子的次数>=2
然后求lcm(a,b)
一个正整数T表示数据组数
接下来T行 每行两个正整数 表示N、M
T行 每行一个整数 表示第i组数据的结果
4
2 4
3 3
6 5
8 3
24
28
233
178
HINT
T <= 10000
N, M<=4000000
枚举每个合法的d
然后用合法的更新它的倍数,根据调和级数,那么这是的
#include <iostream>#include <cstdio>#include <algorithm>#include <cmath>#define siji(i,x,y) for(int i=(x);i<=(y);++i)#define gongzi(j,x,y) for(int j=(x);j>=(y);--j)#define xiaosiji(i,x,y) for(int i=(x);i<(y);++i)#define MAXN 100005//#define ivorysiusing namespace std;typedef long long ll;const int N=4000000;bool nonprime[N+5];int prime[N+5],tot,miu[N+5],n,m,ans,T,func[N+5];int sum(int x,int y) {return (x*(x+1)/2)*(y*(y+1)/2);}int main() {#ifdef ivorysifreopen("f1.in","r",stdin);#endifmiu[1]=1;siji(i,2,N) {if(!nonprime[i]) {prime[++tot]=i;miu[i]=-1;}siji(j,1,tot) {if(prime[j]>N/i) break;nonprime[i*prime[j]]=1;if(i%prime[j]==0) break;miu[i*prime[j]]=-miu[i];}}siji(i,1,N) {if(miu[i]==0) continue;int t=i;while(t<=N) {func[t]+=t/i*t*miu[t/i];t+=i;}}siji(i,1,N) {func[i]+=func[i-1];}scanf("%d",&T);while(T--) {ans=0;scanf("%d%d",&n,&m);int t=min(n,m),r;for(int i=1;i<=t;i=r+1) {r=min(n/(n/i),m/(m/i));if(r>t) r=t;ans+=sum(n/i,m/i)*(func[r]-func[i-1]);}printf("%d\n",ans&((1<<30)-1));}return 0;}