[BZOJ3994][SDOI2015]约数个数和
2016-02-04 15:01
281 查看
[SDOI2015]约数个数和
Description设d(x)为x的约数个数,给定N、M,求∑ni=1∑mj=1d(ij)\sum_{i=1}^n\sum_{j=1}^md(ij)
Input
输入文件包含多组测试数据。
第一行,一个整数T,表示测试数据的组数。
接下来的T行,每行两个整数N、M。
Output
T行,每行一个整数,表示你所求的答案。
Sample Input
2
7 4
5 6
Sample Output
110
121
HINT
1<=N, M<=50000
1<=T<=50000
Solution
有一个结论:
∑ni=1∑mj=1d(ij)=∑ni=1∑mj=1⌊ni⌋⌊mj⌋[gcd(i,j)==1]\sum_{i=1}^n\sum_{j=1}^md(ij)=\sum_{i=1}^n\sum_{j=1}^m\lfloor\frac n i\rfloor\lfloor\frac m j\rfloor[\gcd(i,j)==1]
然后随便反演就行
【有谁能告诉我这结论是怎么想到的。。
Code
#include <bits/stdc++.h> using namespace std; typedef long long LL; const int MaxN = 50010; int n,m; LL miu[MaxN],d[MaxN],c[MaxN]; int prime[MaxN],flag[MaxN],cnt; inline void kyuu(){ miu[1]=d[1]=1; for(int i=2;i<=50000;i++){ if(!flag[i]) prime[++cnt]=i,miu[i]=-1,d[i]=2,c[i]=1; for(int j=1;j<=cnt && prime[j]*i<=50000;j++){ flag[i*prime[j]]=1; if(i%prime[j]==0){ miu[i*prime[j]]=0; d[i*prime[j]]=d[i]/(c[i]+1)*(c[i]+2); c[prime[j]*i]=c[i]+1; break; } miu[i*prime[j]]=-miu[i]; d[i*prime[j]]=d[i]*2; c[prime[j]*i]=1; } } for(int i=2;i<=50000;i++) miu[i]+=miu[i-1],d[i]+=d[i-1]; } int main() { int T=0; kyuu(); for(scanf("%d",&T);T--;){ scanf("%d%d",&n,&m); LL res=0; for(int i=1,t;i<=n && i<=m;i=t+1) t=min(n/(n/i),m/(m/i)),res+=(miu[t]-miu[i-1])*d[n/i]*d[m/i]; printf("%lld\n",res); } return 0; }
相关文章推荐
- 新一年计划
- 解决 linux下编译make文件报错“/bin/bash^M: 坏的解释器:没有那个文件或目录” 问题
- python输出调试信息
- assert_param的应用
- hdu2072 单词数
- setTimeout的作用域以及this的指向问题
- Codeforces Round #341 (Div. 2)AWet Shark and Odd and Even
- Codeforces Round #340 (Div. 2) E. XOR and Favorite Number
- Java/Android中的函数调用&回调函数&自定义回调函数
- 算法导论的一些读后感
- MyString实现
- 举例说明Java多线程编程中读写锁的使用
- bzoj1193
- 文章标题
- 分布式与集群的联系与区别
- Java实现TCP之Echo客户端和服务端
- STM32启动文件详解
- Xcode里的profile存放路径
- Java基础:修饰符
- Qt编译,imp_CommandLineToArgvW@8问题