TopCoder SRM 569 DIV2 Level3: MegaFactorialDiv2
来源:互联网 发布:电磁炉评测 知乎 编辑:程序博客网 时间:2024/05/22 09:00
Problem Statement
The factorial of the k-th order of a number n is denoted n!k and defined by the following recurrences:
1) n!k = n!(k-1) * (n-1)!k for n > 0 and k > 0
2) n!k = 1 for n = 0
3) n!k = n for k = 0
For example, 7!1 = 7! (the traditional factorial), and 5!3 = 5!2 * 4!3 = (5!1 * 4!2) * 4!3.
You are given ints N and K. Compute the number of distinct divisors of the numberN!K. Return the computed number modulo 1,000,000,009.
1<= N <= 1000, 1 <= K <= 100
Examples:
N=3, K=1, ans=4. 3!1 = 6, 6的因子分别为1,2,3,6
Solution:
1)
4!0 = 4
4!1 = 4!0 * 3!0 * 2!0 * 1!0
= 4!
= 4 * 3 * 2 * 1
4!2 = 4!1 * 3!1 * 2!1 * 1!1
= (4 * 3 * 2 * 1) * (3 * 2 * 1) * (2 * 1) * 1
= (4) * (3*3) * (2*2*2) * (1*1*1*1)
4!3 = 4!2 * 3!2 * 2!2 * 1!2
= (4!1 * 3!1 * 2!1 * 1!1) * (3!1 * 2!1 * 1!1) * (2!1 * 1!1) * (1!1)
= (4!1) * (3!1)2 * (2!1)3 * (1!1)4
= 4*3*2*1 * (3*2*1)2 * (2*1)3 * (1*1*1*1)
= (4) * (3*3*3) * (2*2*2*2*2*2) * (1*1*1*1*1*1*1*1*1*1)
= 41 * 33 * 26 * 110
可以看出 N!K = N^f(N,N,K)*(N-1)^f(N-1,N,k)*...X^f(X,N,K)...2^f(2,N,K)*1^f(1,N,K),f(X,N,K) 表示X在N!K连乘中出现的次数, 1<=X<=N, 当X>N时, f(X, N, K) = 0。
例如 4!1= 4!= 4 * 3* 2 *1,则f(4,4,1)= 1,f(X,N,1) = 1;
4!3 = 41 * 33 * 26 * 110, 则f(3,4,3) = 3, f(2,4,3) = 6.
因为n!k = n!(k-1) * (n-1)!k, 所以f(X,N,K) = f(X, N, K-1) + f(X, N-1, K).
2<=X=N, 1<= k <=K, f(X,1,k) = 0;
1<= n <=N; x<=n f(X,n, 1) = 1, x > n f(X, n, 1) = 0,
可以递推求得f(X,N,K)值,时间复杂度O(X*N*K), 因为X<=N,所以为O(N^2*K)。
其实对于公式f(X,N,K) = f(X, N, K-1) + f(X, N-1, K)来说,X值并不改变,f(x, n, k) = f(x+1, n+1, k)= f(x+T, n+T, k)
这样只需要计算出f(2, n, k), f(x,n,k) = f(2, n-x+2, k), 这样时间复杂度降至O(N*K).
2) 对于一个正整数n, 怎样求其因子个数之和? 假设n = p1^e1 * p2^e2*...*pt^et,则因子个数之和= (e1+1)*(e2+1)*...(et+1)。其中pi表示小于等于n的所有素数。
Code
#include "stdafx.h"#include <iostream>using namespace std;int MOD = 1000000009;class MegaFactorialDiv2{long map[1001][101];bool IsPrime[1001];public:int countDivisors(int N, int K){if (N == 0){return 1;}if (K == 0){return N % MOD;}for(int n = 1; n <= N;n++){map[n][1] = 1;}for (int k = 1; k <= K; k++){map[1][k] = 0;}for (int i = 2; i <= N; i++){for(int j = 2; j <= K; j++){map[i][j] = (map[i-1][j] + map[i][j-1]) % MOD;}}long long ans = 1;for(int i = 2; i <=N; i++){IsPrime[i] = true;}for(int p = 2; p <= N; p++){if (IsPrime[p]){for(int j = 2*p; j <=N; j+=p){IsPrime[j] = false;}long e = ((primeAppears(N,K,p) + 1) % MOD);ans = (ans * e) % MOD;if (ans < 0 ){cout << ans <<endl;}}}return (int)(ans % MOD);}// The number of times prime factor p appears in the factorization of N!klong primeAppears(int N, int K, int p){long long res = 0;// For each factor x:for (int x = 2 ; x <= N; x++) {int y = x;while ( y%p == 0) {y /= p;res += map[N-x+2][K];res = res % MOD;}}if (res < 0){cout <<res <<endl;}return (long)(res % MOD);}};int _tmain(int argc, _TCHAR* argv[]){MegaFactorialDiv2 * a = new MegaFactorialDiv2();int ans = a->countDivisors(1000, 100);cout <<ans << endl;return 0;}
总结
1. 这题主要考察动态规划和数学知识,刚开始我走进了牛角尖,一直想求出f(x,n,k)的通项公式(二项式定理),导致一直在演算,反而效果不好。
2. 这题主要的技巧在于最后X的降维,将三维将为两维,降低时间复杂度;
3. 程序中需要注意乘积溢出问题,用long long 存储中间结果。
- TopCoder SRM 569 DIV2 Level3: MegaFactorialDiv2
- topcoder SRM 500 div2 level3
- topcoder SRM 492 div2 level3
- topcoder SRM 513 DIV2
- TopCoder SRM 543 DIV2
- topcoder-srm-233-div2
- Topcoder SRM Div2 Level2
- TopCoder SRM 144 div2
- TOPCODER SRM 612 DIV2
- TOPCODER SRM 613 DIV2
- topcoder-srm-613-div2
- topcoder-srm-604-div2
- topcoder-srm-595-div2
- Topcoder SRM 676 div2
- Topcoder SRM 677 div2
- Topcoder SRM 688 div2
- Topcoder SRM 687 div2
- Topcoder srm div2 500
- js/jquery问题
- 视频图像处理中的频域下采样技术
- 关于Oralce数据库优化的几点总结
- centos6.2 更新yum源
- Ubuntu 12.04 64 位版本运行32位可执行文件
- TopCoder SRM 569 DIV2 Level3: MegaFactorialDiv2
- 设计模式之简单工厂.
- linux eclipse 编译 c 程序 Helloworld
- PogoPlug折腾全过程--Debian系统配置及优化
- 正则表达式引擎的构建——基于编译原理DFA(龙书第三章)——3 计算4个函数
- 当前日期+随机数+文件名(采用两种方法实现的工具类)
- 选择排序不是稳定排序
- C/C++的就业,发展方向
- cocos2d-x 纹理深入研究 第二部分