Project Euler problem 12
2012-11-03 18:29
363 查看
就是问前多少项的和的因子个数大于500
输出这个和
最裸的想法就是枚举n,算出前n项和的因子个数
注意算一个数x的因子个数可以在sqrt(x)时间内算出来
但是前n项和是n^2级别的所以。
这样算出来还是 n^2复杂度的。
其实可以进行优化。
由于我们已经知道前n项和是 n * (n + 1) /2
而n和(n + 1)必然有一个偶数
那么前n个数的和必然能表示成两个数的乘积 分别设为x, y
分奇偶讨论一下就知道这两个数是啥了
然后呢有个结论。
一个数,能表示成若干素数p1,p2,p3....的若干次方x1,x2,x3..的乘积
a = p1 ^ x1 * p2 ^ x2 * p3 ^ x3 ......
那么因子个数就是(x1 + 1) * (x2 + 1) * (x3 + 1) * ........
这还是比较好理解的。
那么直接分解这两个数的素因子好了。然后前n项和的素因子各有多少次方也就算出来了
最后优化成 n * sqrt(n)级别的。
其实吧n和 (n + 1) 他俩是必然互素的。
那么x, y那俩数也是互素
然后求因子这个东西是个积性函数。
所以分别求出因子个数直接乘就行了。
刚开始我不知道范围是多少 直接筛了个500W的素数上去
不过算出来一看还是比较小的。 但是如果按1S的标准来算。 O(n^2)的算法还是够呛的。
输出这个和
最裸的想法就是枚举n,算出前n项和的因子个数
注意算一个数x的因子个数可以在sqrt(x)时间内算出来
但是前n项和是n^2级别的所以。
这样算出来还是 n^2复杂度的。
其实可以进行优化。
由于我们已经知道前n项和是 n * (n + 1) /2
而n和(n + 1)必然有一个偶数
那么前n个数的和必然能表示成两个数的乘积 分别设为x, y
分奇偶讨论一下就知道这两个数是啥了
然后呢有个结论。
一个数,能表示成若干素数p1,p2,p3....的若干次方x1,x2,x3..的乘积
a = p1 ^ x1 * p2 ^ x2 * p3 ^ x3 ......
那么因子个数就是(x1 + 1) * (x2 + 1) * (x3 + 1) * ........
这还是比较好理解的。
那么直接分解这两个数的素因子好了。然后前n项和的素因子各有多少次方也就算出来了
最后优化成 n * sqrt(n)级别的。
其实吧n和 (n + 1) 他俩是必然互素的。
那么x, y那俩数也是互素
然后求因子这个东西是个积性函数。
所以分别求出因子个数直接乘就行了。
刚开始我不知道范围是多少 直接筛了个500W的素数上去
不过算出来一看还是比较小的。 但是如果按1S的标准来算。 O(n^2)的算法还是够呛的。
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <vector> #include <queue> #include <set> #include <stack> #include <cmath> #include <map> #include <ctime> #define MAXN 111111 #define INF 100000007 using namespace std; bool tag[5000001]; int p[1000001]; int cnt; void get_prime() //筛出5000000内素数 { cnt = 0; tag[1] = 1; for (int i = 2; i < 5000000; i++) { if (!tag[i]) p[cnt++] = i; for (int j = 0; j < cnt && p[j] * i < 5000000; j++) { tag[i*p[j]] = 1; if (i % p[j] == 0) break; } } } map<int, int>mp; void gao(int x) { for(int i = 0; i < cnt && p[i] * p[i] <= x; i++) { if(x % p[i] == 0) { int tmp = 0; while(x % p[i] == 0) x /= p[i], tmp++; mp[p[i]] += tmp; } } if(x != 1) mp[x]++; } int get() { map<int, int>::iterator it; int ans = 1; for(it = mp.begin(); it != mp.end(); it++) ans = ans * (it -> second + 1); return ans; } int main() { get_prime(); for(int i = 2; ; i++) { mp.clear(); int n = i; int m = n + 1; if(n % 2 == 0) n /= 2; if(m % 2 == 0) m /= 2; gao(n); gao(m); if(get() > 500) { printf("%d\n", n * m); break; } } return 0; }
相关文章推荐
- projecteuler problem 12
- project euler problem 12
- Project Euler Problem 12: Highly divisible triangular number
- Project Euler Problem 12
- Project Euler -> problem 12
- project euler Problem 25
- Project Euler problem 4
- Project Euler Problem 66
- Project Euler problem 34
- Project Euler problem 43
- Project Euler problem 62
- project euler problem 11:Largest product in a grid
- project euler problem 14
- project euler problem 19 数周末
- http://projecteuler.net/problem=20 [Answer:648]
- http://projecteuler.net/problem=34 [Answer:40730]
- project euler problem 11
- Project Euler Problem 58
- Project Euler Problem 27小结
- Project Euler Problem 05 C# solution