[关闭]
@ivorysi 2018-01-05T00:27:19.000000Z 字数 19877 阅读 1407

数论函数学习笔记

笔记


积性函数

对于互质的两个数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

则他们也满足







它还有另一种形式

若两个函数满足






BZOJ 1257: [CQOI2007]余数之和sum

Description

给出正整数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

Input

输入仅一行,包含两个整数n, k。

Output

输出仅一行,即j(n, k)。

Sample Input

5 3

Sample Output

7

HINT

50%的数据满足:1<=n, k<=1000 100%的数据满足:1<=n ,k<=10^9

题解

可以拆式子


取值只有
因为如果,那么有种不同取值,时,取值只能在以内,那么值只有

代码

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <algorithm>
  4. #include <cstring>
  5. #include <vector>
  6. #include <cmath>
  7. #define siji(i,x,y) for(int i=(x);i<=(y);++i)
  8. #define gongzi(j,x,y) for(int j=(x);j>=(y);--j)
  9. #define xiaosiji(i,x,y) for(int i=(x);i<(y);++i)
  10. //#define ivorysi
  11. using namespace std;
  12. typedef long long ll;
  13. int n,k;
  14. ll ans;
  15. int main() {
  16. #ifdef ivorysi
  17. freopen("f1.in","r",stdin);
  18. #endif
  19. scanf("%d%d",&n,&k);
  20. if(n>k) {
  21. ans=(ll)(n-k)*k;
  22. n=k;
  23. }
  24. int t,r;
  25. for(int i=1;i<=n;i=r+1) {
  26. t=k/i;r=k/t;
  27. if(r>n) r=n;
  28. ans+=(ll)(r-i+1)*k-(ll)(r-i+1)*(i+r)/2*t;
  29. }
  30. printf("%lld\n",ans);
  31. return 0;
  32. }

BZOJ 2705: [SDOI2012]Longge的问题

Description

Longge的数学成绩非常好,并且他非常乐于挑战高难度的数学问题。现在问题来了:给定一个整数N,你需要求出∑gcd(i, N)(1<=i <=N)。

Input

一个整数,为N。

Output

一个整数,为所求的答案。

Sample Input

6

Sample Output

15

HINT

【数据范围】
对于60%的数据,0 对于100%的数据,0

题解


如何快速求出这
我们枚举每个质因子有几个就好了,可以dfs

代码

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <algorithm>
  4. #include <cstring>
  5. #include <vector>
  6. #include <cmath>
  7. #define siji(i,x,y) for(int i=(x);i<=(y);++i)
  8. #define gongzi(j,x,y) for(int j=(x);j>=(y);--j)
  9. #define xiaosiji(i,x,y) for(int i=(x);i<(y);++i)
  10. #define MAXN 1000005
  11. //#define ivorysi
  12. using namespace std;
  13. typedef long long ll;
  14. ll n;
  15. ll ans;
  16. ll prime[MAXN];
  17. int cnt[MAXN],tot;
  18. void dfs(int dep,ll now,ll eu) {
  19. if(dep>tot) {
  20. ans+=(n/now)*eu;
  21. return;
  22. }
  23. dfs(dep+1,now,eu);
  24. ll t=1;
  25. siji(i,1,cnt[dep]) {
  26. t=t*prime[dep];
  27. dfs(dep+1,now*t,eu*t/prime[dep]*(prime[dep]-1));
  28. }
  29. }
  30. int main() {
  31. #ifdef ivorysi
  32. freopen("f1.in","r",stdin);
  33. #endif
  34. scanf("%lld",&n);
  35. int t=n;
  36. for(int i=2;i<=t/i;++i) {
  37. if(t%i==0) {
  38. prime[++tot]=i;
  39. while(t%i==0) {
  40. ++cnt[tot];
  41. t/=i;
  42. }
  43. }
  44. }
  45. if(t!=1) {
  46. prime[++tot]=t;
  47. cnt[tot]=1;
  48. }
  49. dfs(1,1,1);
  50. printf("%lld\n",ans);
  51. return 0;
  52. }

BZOJ 2226: [Spoj 5971] LCMSum

Description

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.

Input

The first line contains T the number of test cases. Each of the next T lines contain an integer n.

Output

Output T lines, one for each test case, containing the required sum.

Sample Input

3
1
2
5

Sample Output

1
4
55

HINT

Constraints
1 <= T <= 300000
1 <= n <= 1000000

题解

除法比乘法慢了那么多!!!
这道题卡常!!!

我们预处理每个数的与它互质且比它小的数的和,然后对于每个n枚举约数
拼命卡常啊QAQ

代码

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <algorithm>
  4. #include <cstring>
  5. #include <vector>
  6. #include <cmath>
  7. #define siji(i,x,y) for(int i=(x);i<=(y);++i)
  8. #define gongzi(j,x,y) for(int j=(x);j>=(y);--j)
  9. #define xiaosiji(i,x,y) for(int i=(x);i<(y);++i)
  10. #define MAXN 1000005
  11. //#define ivorysi
  12. using namespace std;
  13. typedef long long ll;
  14. ll phi[MAXN*2];
  15. bool nonprime[MAXN*2];
  16. int prime[MAXN*2],tot;
  17. int T,n;
  18. ll ans;
  19. int read() {
  20. char c=getchar();
  21. int res=0;
  22. while(c<'0' || c>'9') c=getchar();
  23. while(c>='0' && c<='9') {
  24. res=res*10+c-'0';
  25. c=getchar();
  26. }
  27. return res;
  28. }
  29. void out(ll x) {
  30. if(x>=10) {
  31. out(x/10);
  32. }
  33. putchar('0'+x%10);
  34. }
  35. int main() {
  36. #ifdef ivorysi
  37. freopen("f1.in","r",stdin);
  38. #endif
  39. phi[1]=1;
  40. siji(i,2,1000000) {
  41. if(!nonprime[i]) {
  42. phi[i]=i-1;
  43. prime[++tot]=i;
  44. }
  45. siji(j,1,tot) {
  46. if((ll)prime[j]*i>1000000) break;
  47. nonprime[i*prime[j]]=1;
  48. if(i%prime[j]==0) {
  49. phi[i*prime[j]]=phi[i]*prime[j];
  50. break;
  51. }
  52. phi[i*prime[j]]=phi[i]*(prime[j]-1);
  53. }
  54. }
  55. siji(i,2,1000000) phi[i]=phi[i]*i/2;
  56. T=read();
  57. while(T--) {
  58. n=read();
  59. ans=0;
  60. for(int i=1;i*i<=n;++i) {
  61. if(n%i==0) {
  62. ans+=phi[i];
  63. if(i*i<n) {ans+=phi[n/i];}
  64. }
  65. }
  66. ans=ans*n;
  67. out(ans);
  68. putchar('\n');
  69. }
  70. return 0;
  71. }

BZOJ 1101: [POI2007]Zap

Description

FGD正在破解一段密码,他需要回答很多类似的问题:对于给定的整数a,b和d,有多少正整数对x,y,满足x<=a
,y<=b,并且gcd(x,y)=d。作为FGD的同学,FGD希望得到你的帮助。

Input

第一行包含一个正整数n,表示一共有n组询问。(1<=n<= 50000)接下来n行,每行表示一个询问,每行三个
正整数,分别为a,b,d。(1<=d<=a,b<=50000)

Output

对于每组询问,输出到输出文件zap.out一个正整数,表示满足条件的整数对数。

Sample Input

2
4 5 2
6 4 3

Sample Output

3
2
//对于第一组询问,满足条件的整数对有(2,2),(2,4),(4,2)。对于第二组询问,满足条件的整数对有(
6,3),(3,3)。

题解

我们转化一下
之间有多少个互质的数
以下还用表示区间左右端点
然后列出式子




然后因为只有种取值,且每段都对应一段连续的取值,然后这个东西的取值不超过

代码

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <algorithm>
  4. #include <cstring>
  5. #include <vector>
  6. #include <cmath>
  7. #define siji(i,x,y) for(int i=(x);i<=(y);++i)
  8. #define gongzi(j,x,y) for(int j=(x);j>=(y);--j)
  9. #define xiaosiji(i,x,y) for(int i=(x);i<(y);++i)
  10. #define MAXN 1000005
  11. //#define ivorysi
  12. using namespace std;
  13. typedef long long ll;
  14. const int N = 50000;
  15. int miu[N+10],prime[N+10],tot,sum[N+10],T;
  16. bool nonprime[N+10];
  17. ll ans=0;
  18. int main() {
  19. #ifdef ivorysi
  20. freopen("f1.in","r",stdin);
  21. #endif
  22. miu[1]=1;
  23. siji(i,2,N) {
  24. if(!nonprime[i]) {
  25. prime[++tot]=i;
  26. miu[i]=-1;
  27. }
  28. siji(j,1,tot) {
  29. if(i*prime[j]>N) break;
  30. nonprime[i*prime[j]]=1;
  31. if(i%prime[j]==0) break;
  32. miu[i*prime[j]]=-miu[i];
  33. }
  34. }
  35. siji(i,1,N) {
  36. sum[i]=sum[i-1]+miu[i];
  37. }
  38. scanf("%d",&T);
  39. int a,b,d;
  40. while(T--) {
  41. scanf("%d%d%d",&a,&b,&d);
  42. a/=d;b/=d;
  43. ans=0;
  44. int n=min(a,b);
  45. int r;
  46. for(int i=1;i<=n;i=r+1) {
  47. r=min(a/(a/i),b/(b/i));
  48. if(r>n) r=n;
  49. ans+=(ll)(a/i)*(b/i)*(sum[r]-sum[i-1]);
  50. }
  51. printf("%lld\n",ans);
  52. }
  53. return 0;
  54. }

BZOJ 2440: [中山市选2011]完全平方数

Description

小 X 自幼就很喜欢数。但奇怪的是,他十分讨厌完全平方数。他觉得这些
数看起来很令人难受。由此,他也讨厌所有是完全平方数的正整数倍的数。然而
这丝毫不影响他对其他数的热爱。
这天是小X的生日,小 W 想送一个数给他作为生日礼物。当然他不能送一
个小X讨厌的数。他列出了所有小X不讨厌的数,然后选取了第 K个数送给了
小X。小X很开心地收下了。
然而现在小 W 却记不起送给小X的是哪个数了。你能帮他一下吗?

Input

包含多组测试数据。文件第一行有一个整数 T,表示测试
数据的组数。
第2 至第T+1 行每行有一个整数Ki,描述一组数据,含义如题目中所描述。

Output

含T 行,分别对每组数据作出回答。第 i 行输出相应的
第Ki 个不是完全平方数的正整数倍的数。

Sample Input

4
1
13
100
1234567

Sample Output

1
19
163
2030745

HINT

对于 100%的数据有 1 ≤ Ki ≤ 10^9,T ≤ 50

题解

这道题考虑容斥原理,和的性质
二分一个x,考虑快速之间有多少个非完全平方数的个数
这个就相当于,1的倍数,减去1个质数平方的倍数,加上2个质数平方的倍数……
发现这个东西符号刚好和的正负一样

代码

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <algorithm>
  4. #include <cstring>
  5. #include <vector>
  6. #include <cmath>
  7. #define siji(i,x,y) for(int i=(x);i<=(y);++i)
  8. #define gongzi(j,x,y) for(int j=(x);j>=(y);--j)
  9. #define xiaosiji(i,x,y) for(int i=(x);i<(y);++i)
  10. #define MAXN 1000005
  11. //#define ivorysi
  12. using namespace std;
  13. typedef long long ll;
  14. const int N = 100000;
  15. int miu[N+10],prime[N+10],tot,sum[N+10],T;
  16. bool nonprime[N+10];
  17. ll ans=0;
  18. ll check(ll mid) {
  19. ll res=0;
  20. for(ll i=1;i*i<=mid;++i) {
  21. if(miu[i]==0) continue;
  22. res+=(ll)miu[i]*(mid/(i*i));
  23. }
  24. return res;
  25. }
  26. int main() {
  27. #ifdef ivorysi
  28. freopen("f1.in","r",stdin);
  29. #endif
  30. miu[1]=1;
  31. siji(i,2,N) {
  32. if(!nonprime[i]) {
  33. prime[++tot]=i;
  34. miu[i]=-1;
  35. }
  36. siji(j,1,tot) {
  37. if(i*prime[j]>N) break;
  38. nonprime[i*prime[j]]=1;
  39. if(i%prime[j]==0) break;
  40. miu[i*prime[j]]=-miu[i];
  41. }
  42. }
  43. scanf("%d",&T);
  44. ll k;
  45. while(T--) {
  46. scanf("%lld",&k);
  47. ll l=1,r=10000000000LL;
  48. while(l<r) {
  49. ll mid=(l+r)>>1;
  50. if(check(mid)>=k) r=mid;
  51. else l=mid+1;
  52. }
  53. printf("%lld\n",r);
  54. }
  55. return 0;
  56. }

BZOJ 2820: YY的GCD

Description

神犇YY虐完数论后给傻×kAc出了一题给定N, M,求1<=x<=N, 1<=y<=M且gcd(x, y)为质数的(x, y)有多少对kAc这种
傻×必然不会了,于是向你来请教……多组输入

Input

第一行一个整数T 表述数据组数接下来T行,每行两个正整数,表示N, M

Output

T行,每行一个整数表示第i组数据的结果

Sample Input

2
10 10
100 100

Sample Output

30
2791

HINT

T = 10000
N, M <= 10000000

题解

这道题按照之前某道1101的思路,可以很容易想到一个超时思路
枚举一个质数

然后我们可以设

我们只要能求出对于然后处理成前缀和就很妙了,就变成1101了
然后我们枚举每个质数,去更新它的倍数的话,根据调和级数,均摊是
然后质数一共有个所以复杂度是可以暴力预处理

代码

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <algorithm>
  4. #include <cstring>
  5. #include <vector>
  6. #include <cmath>
  7. #define siji(i,x,y) for(int i=(x);i<=(y);++i)
  8. #define gongzi(j,x,y) for(int j=(x);j>=(y);--j)
  9. #define xiaosiji(i,x,y) for(int i=(x);i<(y);++i)
  10. #define MAXN 10000005
  11. //#define ivorysi
  12. using namespace std;
  13. typedef long long ll;
  14. ll sum[MAXN];
  15. bool nonprime[MAXN];
  16. int prime[MAXN],tot,n,m,miu[MAXN];
  17. int main() {
  18. #ifdef ivorysi
  19. freopen("f1.in","r",stdin);
  20. #endif
  21. miu[1]=1;
  22. siji(i,2,10000000) {
  23. if(!nonprime[i]) {
  24. prime[++tot]=i;
  25. miu[i]=-1;
  26. }
  27. siji(j,1,tot) {
  28. if(i>10000000/prime[j]) break;
  29. nonprime[i*prime[j]]=1;
  30. if(i%prime[j]==0) break;
  31. miu[i*prime[j]]=-miu[i];
  32. }
  33. }
  34. siji(i,1,tot) {
  35. int t=prime[i];
  36. while(t<=10000000) sum[t]+=miu[t/prime[i]],t+=prime[i];
  37. }
  38. siji(i,1,10000000) sum[i]+=sum[i-1];
  39. int T;
  40. scanf("%d",&T);
  41. while(T--) {
  42. scanf("%d%d",&n,&m);
  43. int t=min(n,m),r;
  44. ll ans=0;
  45. for(int i=1;i<=t;i=r+1) {
  46. r=min(n/(n/i),m/(m/i));
  47. if(r>t) r=t;
  48. ans+=(ll)(sum[r]-sum[i-1])*(n/i)*(m/i);
  49. }
  50. printf("%lld\n",ans);
  51. }
  52. return 0;
  53. }

BZOJ 2005: [Noi2010]能量采集

Description

栋栋有一块长方形的地,他在地上种了一种能量植物,这种植物可以采集太阳光的能量。在这些植物采集能量后,
栋栋再使用一个能量汇集机器把这些植物采集到的能量汇集到一起。 栋栋的植物种得非常整齐,一共有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的能
量损失。

Input

仅包含一行,为两个整数n和m。

Output

仅包含一个整数,表示总共产生的能量损失。

Sample Input

【样例输入1】

5 4

【样例输入2】

3 4

Sample Output

【样例输出1】

36

【样例输出2】

20

对于100%的数据:1 ≤ n, m ≤ 100,000。

题解

这道题只要想起来某个公式,还是很简单的
这个公式就是

这个东西可以通过数学归纳法证明,就是证明如果n是一个质数的指数幂,然后n是两个质数的指数幂……就证出来了
然后我们可以列式子

然后我们发现最难算的是这个(废话)




这道题就愉快的出解了

代码

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <algorithm>
  4. #include <cstring>
  5. #include <vector>
  6. #include <cmath>
  7. #define siji(i,x,y) for(int i=(x);i<=(y);++i)
  8. #define gongzi(j,x,y) for(int j=(x);j>=(y);--j)
  9. #define xiaosiji(i,x,y) for(int i=(x);i<(y);++i)
  10. #define MAXN 100005
  11. //#define ivorysi
  12. using namespace std;
  13. typedef long long ll;
  14. ll sum[MAXN];
  15. bool nonprime[MAXN];
  16. int prime[MAXN],tot,n,m,phi[MAXN];
  17. int main() {
  18. #ifdef ivorysi
  19. freopen("f1.in","r",stdin);
  20. #endif
  21. phi[1]=1;
  22. siji(i,2,100000) {
  23. if(!nonprime[i]) {
  24. prime[++tot]=i;
  25. phi[i]=i-1;
  26. }
  27. siji(j,1,tot) {
  28. if(i>100000/prime[j]) break;
  29. nonprime[i*prime[j]]=1;
  30. if(i%prime[j]==0) {
  31. phi[i*prime[j]]=phi[i]*prime[j];
  32. break;
  33. }
  34. phi[i*prime[j]]=phi[i]*(prime[j]-1);
  35. }
  36. }
  37. siji(i,1,100000) phi[i]+=phi[i-1];
  38. scanf("%d%d",&n,&m);
  39. int t=min(n,m),r;
  40. ll ans=0;
  41. for(int i=1;i<=t;i=r+1) {
  42. r=min(n/(n/i),m/(m/i));
  43. if(r>t) r=t;
  44. ans+=(ll)(phi[r]-phi[i-1])*(n/i)*(m/i);
  45. }
  46. ans=ans*2;
  47. ans-=(ll)n*m;
  48. printf("%lld\n",ans);
  49. return 0;
  50. }

BZOJ 3529: [Sdoi2014]数表

Description

有一张N×m的数表,其第i行第j列(1 < =i < =礼,1 < =j < =m)的数值为
能同时整除i和j的所有自然数之和。给定a,计算数表中不大于a的数之和。

Input

输入包含多组数据。
输入的第一行一个整数Q表示测试点内的数据组数,接下来Q行,每行三个整数n,m,a(|a| < =10^9)描述一组数据。

Output

对每组数据,输出一行一个整数,表示答案模2^31的值。

Sample Input

2
4 4 3
10 10 5

Sample Output

20
148

HINT

1 < =N.m < =10^5 , 1 < =Q < =2×10^4

题解

满足然后
我们可以这么算
设g(p)表示以p为最大公约数的对数有多少个




然后这个式子就可以改成


我们可以线性递推出
我们发现如果 那么约数和是
如果 那么约数和是
我们需要把维护成一个前缀和,就可以快速处理了
考虑到我们离线处理,把询问按a排序,把排序,然后不断加入并更新到i的倍数上,用树状数组维护前缀和
然后这个东西是
每次询问是
总复杂度是

代码

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <algorithm>
  4. #include <cmath>
  5. #define siji(i,x,y) for(int i=(x);i<=(y);++i)
  6. #define gongzi(j,x,y) for(int j=(x);j>=(y);--j)
  7. #define xiaosiji(i,x,y) for(int i=(x);i<(y);++i)
  8. #define MAXN 100005
  9. //#define ivorysi
  10. using namespace std;
  11. typedef long long ll;
  12. const int mod=(1<<30)-1+(1<<30);
  13. const int N=100000;
  14. int Q;
  15. int g[N+5],prime[N+5],tot,miu[N+5],pos[N+5],ans[N+5],tr[N+5];
  16. int f[N+5];
  17. bool nonprime[N*2];
  18. struct node {
  19. int n,m,id,a;
  20. bool operator < (const node &rhs) const {
  21. return a<rhs.a;
  22. }
  23. }qry[N];
  24. bool cmp(int a,int b) {
  25. return f[a]<f[b];
  26. }
  27. int lowbit(int x) {return x&(-x);}
  28. void Insert(int pos,int x) {
  29. if(x==0) return;
  30. while(pos<=N) {
  31. tr[pos]+=x;
  32. pos+=lowbit(pos);
  33. }
  34. }
  35. int query(int pos) {
  36. int res=0;
  37. while(pos>0) {
  38. res+=tr[pos];
  39. pos-=lowbit(pos);
  40. }
  41. return res;
  42. }
  43. int _query(int l,int r) {
  44. return query(r)-query(l-1);
  45. }
  46. int main() {
  47. #ifdef ivorysi
  48. freopen("f1.in","r",stdin);
  49. #endif
  50. miu[1]=1;
  51. f[1]=1;
  52. siji(i,2,N) {
  53. if(!nonprime[i]) {
  54. prime[++tot]=i;
  55. miu[i]=-1;
  56. f[i]=i+1;
  57. }
  58. siji(j,1,tot) {
  59. if(prime[j]>N/i) break;
  60. nonprime[i*prime[j]]=1;
  61. if(i%prime[j]==0) {
  62. f[i*prime[j]]=((ll)(f[i]-f[i/prime[j]])*prime[j]+f[i]);
  63. break;
  64. }
  65. miu[i*prime[j]]=-miu[i];
  66. f[i*prime[j]]=f[i]*prime[j]+f[i];
  67. }
  68. }
  69. siji(i,1,N) pos[i]=i;
  70. sort(pos+1,pos+N+1,cmp);
  71. scanf("%d",&Q);
  72. siji(i,1,Q) {
  73. scanf("%d%d%d",&qry[i].n,&qry[i].m,&qry[i].a);
  74. qry[i].id=i;
  75. }
  76. sort(qry+1,qry+Q+1);
  77. int now=1;
  78. siji(i,1,Q) {
  79. while(now<=N && f[pos[now]]<=qry[i].a) {
  80. int t=pos[now];
  81. while(t<=N) {
  82. Insert(t,(f[pos[now]]&mod)*miu[t/pos[now]]);
  83. t+=pos[now];
  84. }
  85. ++now;
  86. }
  87. int t=min(qry[i].n,qry[i].m),r;
  88. for(int j=1;j<=t;j=r+1) {
  89. r=min(qry[i].n/(qry[i].n/j),qry[i].m/(qry[i].m/j));
  90. if(r>t) r=t;
  91. ans[qry[i].id]+=_query(j,r)*(qry[i].n/j)*(qry[i].m/j);
  92. }
  93. ans[qry[i].id]&=mod;
  94. }
  95. siji(i,1,Q) {
  96. printf("%d\n",ans[i]);
  97. }
  98. return 0;
  99. }

BZOJ 2154: Crash的数字表格

Description

今天的数学课上,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的值。

Input

输入的第一行包含两个正整数,分别表示N和M。

Output

输出一个正整数,表示表格中所有数的和mod 20101009的值。

Sample Input

4 5

Sample Output

122

【数据规模和约定】

100%的数据满足N, M ≤ 10^7。

题解

严谨认真的推一下式子

我们枚举约数,然后表示互质的和

然后考虑怎么求





枚举的,计算的,总体是的,已经可以解决本题

代码

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <algorithm>
  4. #include <cmath>
  5. #define siji(i,x,y) for(int i=(x);i<=(y);++i)
  6. #define gongzi(j,x,y) for(int j=(x);j>=(y);--j)
  7. #define xiaosiji(i,x,y) for(int i=(x);i<(y);++i)
  8. #define MAXN 100005
  9. #define mod 20101009
  10. //#define ivorysi
  11. using namespace std;
  12. typedef long long ll;
  13. const int N=10000000;
  14. bool nonprime[N+5];
  15. int prime[N+5],tot,miu[N+5],n,m,ans;
  16. int sum(int x,int y) {
  17. return (1LL*x*(x+1)/2%mod*(1LL*y*(y+1)/2%mod))%mod;
  18. }
  19. int calc(int x,int y) {
  20. int t=min(x,y),r;
  21. int res=0;
  22. for(int i=1;i<=t;i=r+1) {
  23. r=min(x/(x/i),y/(y/i));
  24. if(r>t) r=t;
  25. res+=1LL*sum(x/i,y/i)*(miu[r]-miu[i-1])%mod;
  26. res=(res%mod+mod)%mod;
  27. }
  28. return res;
  29. }
  30. int main() {
  31. #ifdef ivorysi
  32. freopen("f1.in","r",stdin);
  33. #endif
  34. miu[1]=1;
  35. siji(i,2,N) {
  36. if(!nonprime[i]) {
  37. prime[++tot]=i;
  38. miu[i]=-1;
  39. }
  40. siji(j,1,tot) {
  41. if(prime[j]>N/i) break;
  42. nonprime[i*prime[j]]=1;
  43. if(i%prime[j]==0) break;
  44. miu[i*prime[j]]=-miu[i];
  45. }
  46. }
  47. siji(i,1,N) miu[i]=1LL*i*i%mod*miu[i]%mod;
  48. siji(i,1,N) miu[i]+=miu[i-1],miu[i]%=mod;
  49. scanf("%d%d",&n,&m);
  50. int r,t=min(n,m);
  51. for(int i=1;i<=t;i=r+1) {
  52. r=min(n/(n/i),m/(m/i));
  53. if(r>t) r=t;
  54. ans+=calc(n/i,m/i)*(1LL*(i+r)*(r-i+1)/2%mod)%mod;
  55. ans%=mod;
  56. }
  57. ans=(ans%mod+mod)%mod;
  58. printf("%d\n",ans);
  59. return 0;
  60. }

BZOJ 2693: jzptab

Description

()

Input

一个正整数T表示数据组数
接下来T行 每行两个正整数 表示N、M

Output

T行 每行一个整数 表示第i组数据的结果

Sample Input

1
4 5

Sample Output

122

HINT

T <= 10000
N, M<=10000000

题解

我们可以优化一下上一个式子,让它可以满足多组询问



我们发现只要求出
的前缀和我们就可以在中完成一次询问
考虑到,积性函数的约数和还是积性函数


然后我们可以在线性筛的同时求出这个函数值
的时候我们直接让这个函数值乘上即可,因为多出来的约数的贡献全是0,所以直接考虑

代码

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <algorithm>
  4. #include <cmath>
  5. #define siji(i,x,y) for(int i=(x);i<=(y);++i)
  6. #define gongzi(j,x,y) for(int j=(x);j>=(y);--j)
  7. #define xiaosiji(i,x,y) for(int i=(x);i<(y);++i)
  8. #define MAXN 100005
  9. #define mod 100000009
  10. //#define ivorysi
  11. using namespace std;
  12. typedef long long ll;
  13. const int N=10000000;
  14. bool nonprime[N+5];
  15. int prime[N+5],tot,func[N+5],n,m,ans,T;
  16. int sum(int x,int y) {
  17. return (1LL*x*(x+1)/2%mod*(1LL*y*(y+1)/2%mod))%mod;
  18. }
  19. int main() {
  20. #ifdef ivorysi
  21. freopen("f1.in","r",stdin);
  22. #endif
  23. func[1]=1;
  24. siji(i,2,N) {
  25. if(!nonprime[i]) {
  26. prime[++tot]=i;
  27. func[i]=((i-1LL*i*i%mod)%mod+mod)%mod;
  28. }
  29. siji(j,1,tot) {
  30. if(prime[j]>N/i) break;
  31. nonprime[i*prime[j]]=1;
  32. if(i%prime[j]==0) {
  33. func[i*prime[j]]=1LL*prime[j]*func[i]%mod;
  34. break;
  35. }
  36. func[i*prime[j]]=1LL*func[prime[j]]*func[i]%mod;
  37. }
  38. }
  39. siji(i,1,N) func[i]+=func[i-1],func[i]%=mod;
  40. scanf("%d",&T);
  41. while(T--) {
  42. ans=0;
  43. scanf("%d%d",&n,&m);
  44. int t=min(n,m),r;
  45. for(int i=1;i<=t;i=r+1) {
  46. r=min(n/(n/i),m/(m/i));
  47. if(r>t) r=t;
  48. ans+=1LL*sum(n/i,m/i)*(func[r]-func[i-1])%mod;
  49. ans=(ans%mod+mod)%mod;
  50. }
  51. printf("%d\n",ans);
  52. }
  53. return 0;
  54. }

BZOJ 2694: Lcm

Description

对于任意的>1的n gcd(a, b)不是n^2的倍数
也就是说gcd(a, b)没有一个因子的次数>=2
然后求lcm(a,b)

Input

一个正整数T表示数据组数
接下来T行 每行两个正整数 表示N、M

Output

T行 每行一个整数 表示第i组数据的结果

Sample Input

4
2 4
3 3
6 5
8 3

Sample Output

24
28
233
178

HINT

HINT
T <= 10000
N, M<=4000000

题解

枚举每个合法的d


然后用合法的更新它的倍数,根据调和级数,那么这是

代码

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <algorithm>
  4. #include <cmath>
  5. #define siji(i,x,y) for(int i=(x);i<=(y);++i)
  6. #define gongzi(j,x,y) for(int j=(x);j>=(y);--j)
  7. #define xiaosiji(i,x,y) for(int i=(x);i<(y);++i)
  8. #define MAXN 100005
  9. //#define ivorysi
  10. using namespace std;
  11. typedef long long ll;
  12. const int N=4000000;
  13. bool nonprime[N+5];
  14. int prime[N+5],tot,miu[N+5],n,m,ans,T,func[N+5];
  15. int sum(int x,int y) {
  16. return (x*(x+1)/2)*(y*(y+1)/2);
  17. }
  18. int main() {
  19. #ifdef ivorysi
  20. freopen("f1.in","r",stdin);
  21. #endif
  22. miu[1]=1;
  23. siji(i,2,N) {
  24. if(!nonprime[i]) {
  25. prime[++tot]=i;
  26. miu[i]=-1;
  27. }
  28. siji(j,1,tot) {
  29. if(prime[j]>N/i) break;
  30. nonprime[i*prime[j]]=1;
  31. if(i%prime[j]==0) break;
  32. miu[i*prime[j]]=-miu[i];
  33. }
  34. }
  35. siji(i,1,N) {
  36. if(miu[i]==0) continue;
  37. int t=i;
  38. while(t<=N) {
  39. func[t]+=t/i*t*miu[t/i];
  40. t+=i;
  41. }
  42. }
  43. siji(i,1,N) {func[i]+=func[i-1];}
  44. scanf("%d",&T);
  45. while(T--) {
  46. ans=0;
  47. scanf("%d%d",&n,&m);
  48. int t=min(n,m),r;
  49. for(int i=1;i<=t;i=r+1) {
  50. r=min(n/(n/i),m/(m/i));
  51. if(r>t) r=t;
  52. ans+=sum(n/i,m/i)*(func[r]-func[i-1]);
  53. }
  54. printf("%d\n",ans&((1<<30)-1));
  55. }
  56. return 0;
  57. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注