UVA-11526H(n)(数论)
2015-05-21 22:10
363 查看
题目大意是将下面的函数优化:
long long H(int n){long long res = 0;for( int i = 1; i <= n; i=i+1 ){res = (res + n/i);}return res;}
首先给出我自己的算法,应该是正常人类能想到的算法,后面给出一种非正常人类计算出来的算法,就是具体数学上的底的多项式合并。
我的算法是停地向前除,用i记录当前除的数,j表示从后往前计算过的数。由10的分解和式:10,5,3,2,2,1,1,1,1,1可以看出比1小的个数有0个,比2小的数有5个,即10 - 10/2,比3的数有7个,其中5个2,两个2,这样,就可以将i和j表示出来,当i+j <=n的时候结束循环。
这种算法大概比下面的算法慢4,5倍以上,下面给出推导公式(图片来自百度):
下面是我的代码:
long long H(int n){long long res = 0;for( int i = 1; i <= n; i=i+1 ){res = (res + n/i);}return res;}
首先给出我自己的算法,应该是正常人类能想到的算法,后面给出一种非正常人类计算出来的算法,就是具体数学上的底的多项式合并。
我的算法是停地向前除,用i记录当前除的数,j表示从后往前计算过的数。由10的分解和式:10,5,3,2,2,1,1,1,1,1可以看出比1小的个数有0个,比2小的数有5个,即10 - 10/2,比3的数有7个,其中5个2,两个2,这样,就可以将i和j表示出来,当i+j <=n的时候结束循环。
这种算法大概比下面的算法慢4,5倍以上,下面给出推导公式(图片来自百度):
下面是我的代码:
#include <bits/stdc++.h> using namespace std; int main(){ int T; scanf("%d",&T); while (T--){ long long n,sum = 0,i = 1,j = 0; scanf("%lld",&n); while (i+j <= n){ sum += n/i + (n - n/i - j)*(i-1); j = n - n/i; if (i + j == n+1) sum-=n/i; i++; } printf("%lld\n",sum); } return 0; }
相关文章推荐
- 【数论,找规律】Uva 11526 - H(n)
- 【数论】UVa 11526 - H(n)
- UVa 11526 H(n) (数论)
- uva 11526 H(n) (数论)
- UVA 10892 - LCM Cardinality(数论)
- Uva 11426 GCD - Extreme (II)(基本数论)
- UVA 11754 - Code Feat(数论)
- UVA 11526 - H(n)
- UVA 11610 Reverse Prime(数论+树状数组+二分)
- UVA 550 Multiplying by Rotation 数论的规律
- uva 1530 - Floating Point Numbers(数论)
- UVA 106 Fermat vs. Pythagoras(数论)
- UVA 417 - Word Index(数论)
- UVA-575-Skew Binary (简单数论问题)
- UVA 11426 GCD - Extreme (II) (数论|欧拉函数)
- uva 10110 Light, more light (数论)
- UVA 1415 - Gauss Prime(数论,高斯素数拓展)
- UVa 10006 Carmichael Numbers(数论&卡米歇尔数&考塞特判别法)
- UVA 10539 - Almost Prime Numbers(数论)
- UVA 10539 - Almost Prime Numbers(数论)