HDU 1215 七夕节(因子和)
2015-09-04 08:32
399 查看
Description
输出一个数的所有因子和(不包括自身)
Input
输入数据的第一行是一个数字T(1<=T<=500000),它表明测试数据的组数.然后是T组测试数据,每组测试数据只有一个数字n(1<=n<=500000).
Output
对于每组测试数据,请输出一个代表输入数据N的另一半的编号.
Sample Input
3
2
10
20
Sample Output
1
8
22
Solution
因为T非常大,所以首先应该预处理出500000以内所有数的因子和,然后O(1)查询,因此限制的最高时间复杂度也不能超过O(nlogn),对n质因数分解得n=p1^k1*p2^k2*…pm^km,那么轻易得到n的因子和为(p1^0+p1^1+…+p1^k1)(p2^0+p2^1+…+p2^k2)…(pm^0+pm^1+…+pm^km),令t=(p1^0+p1^1+…+p1^k1),通过这个式子不难想出sum
=sum[t]*sum[n/t],由动态规划的思想当处理到sum
时sum[n/t]和sum[t]已经被求出,所以这个式子可以在低于O(nlogn)的时间内处理出n以内所有数的因子和,当然此处还需要用到线性素数筛法提供每个数的最小素因数,注意当n=t时,显然用sum
=sum[t]*sum[n/t]=sum
不能求出sum
,此时再次用到上面那个因子和公式,用等比数列求和得到此时sum
=(mark
*n-1)/(mark
-1)(此处mark
表示n的最小素因数,mark数组在线性筛素数时可以得到)
Code
输出一个数的所有因子和(不包括自身)
Input
输入数据的第一行是一个数字T(1<=T<=500000),它表明测试数据的组数.然后是T组测试数据,每组测试数据只有一个数字n(1<=n<=500000).
Output
对于每组测试数据,请输出一个代表输入数据N的另一半的编号.
Sample Input
3
2
10
20
Sample Output
1
8
22
Solution
因为T非常大,所以首先应该预处理出500000以内所有数的因子和,然后O(1)查询,因此限制的最高时间复杂度也不能超过O(nlogn),对n质因数分解得n=p1^k1*p2^k2*…pm^km,那么轻易得到n的因子和为(p1^0+p1^1+…+p1^k1)(p2^0+p2^1+…+p2^k2)…(pm^0+pm^1+…+pm^km),令t=(p1^0+p1^1+…+p1^k1),通过这个式子不难想出sum
=sum[t]*sum[n/t],由动态规划的思想当处理到sum
时sum[n/t]和sum[t]已经被求出,所以这个式子可以在低于O(nlogn)的时间内处理出n以内所有数的因子和,当然此处还需要用到线性素数筛法提供每个数的最小素因数,注意当n=t时,显然用sum
=sum[t]*sum[n/t]=sum
不能求出sum
,此时再次用到上面那个因子和公式,用等比数列求和得到此时sum
=(mark
*n-1)/(mark
-1)(此处mark
表示n的最小素因数,mark数组在线性筛素数时可以得到)
Code
#include<cstdio> #include<iostream> #include<cstring> using namespace std; #define maxn 500005 int mark[maxn],prime[maxn],cnt;//prime存储素数,从0开始,mark[i]表示i的最小素因数 void Get_Prime(int n)//素数线性筛法 { memset(mark,0,sizeof(mark)); cnt=0; for(int i=2;i<=n;i++) { if(!mark[i]) mark[i]=prime[cnt++]=i; for(int j=0;j<cnt&&prime[j]*i<=n;j++) { mark[i*prime[j]]=prime[j]; if(i%prime[j]==0) break; } } } long long sumall[maxn];//sumall[i]表示i的所有因子和 void Get_all_sum(int n)//求出n以内每个数的因子和 { sumall[1]=1; for(int i=2;i<=n;i++) { int t=1; for(int j=i;j%mark[i]==0;j/=mark[i]) t*=mark[i]; if(i==t) sumall[i]=(1ll*mark[i]*i-1)/(mark[i]-1); else sumall[i]=sumall[t]*sumall[i/t]; } } int main() { Get_Prime(maxn); Get_all_sum(maxn); int T; scanf("%d",&T); while(T--) { int n; scanf("%d",&n); printf("%lld\n",sumall -n);//此处因子不包括n自身 } return 0; }
相关文章推荐
- HDU 1061 Rightmost Digit(快速幂)
- HDU 4497 GCD and LCM(素因子分解+组合数学)
- HDU 1466 计算直线的交点数(dp)
- HDU 1536 S-Nim(博弈论)
- PHP基础----HTML表单的创建与提交----18表单与 PHP
- Threat Intellgence
- POJ 1284 Primitive Roots(欧拉函数)
- POJ 2034 Anti-prime Sequences(数论+dfs)
- POJ 1365 Prime Land(分解质因数)
- POJ 2115 C Looooops(一元线性同余方程)
- POJ 3090 Visible Lattice Points(欧拉函数)
- POJ 2478 Farey Sequence(欧拉函数)
- POJ 2773 Happy 2006(数论)
- PHP基础----常用库函数----17图片打水印实例
- Fragment+RadioButton实现点击切换页面效果
- PHP基础----常用库函数----16生成图片
- C++之随笔(二)
- 关于存储过程可空条件查询
- PHP基础----常用库函数----15文件操作
- PHP基础----常用库函数----14JSON格式数据的操作