POJ3761解题报告

公式的推导在另一篇文章已经给出了详细的推导。在写程序实现时候,主要利用同余性质和快速求幂方法,并且使用了c99中新增的数据类型 long long

程 序:

 

1/*遵循C99,编译时候请加上参数-std=c99*/
2#include <string.h>
3#include <stdio.h>
4#define M 20100713
5int modM[1000010];
6/*充分利用位运算,同余性质,快速求模幂*/
7int mypow(int a, int k)
8{
9 int mi[2], ans[2], i = 0, j = 0;
10 mi[0] = a % M, ans[0] = 1;
11 while(k)
12 {
13 if(k & 1)
14 {
15 ans[i ^ 1] = ((long long)ans[i] * mi[j]) % M;
16 i ^= 1;
17 }
18 mi[j ^ 1] = ((long long)mi[j] * mi[j]) % M;
19 k >>= 1;
20 j ^= 1;
21 }
22 return ans[i];
23}
24int f(int n, int k)
25{
26 return ((long long)mypow(k + 1, n - k) * modM[k]) % M;
27}
28int main()
29{
30 int n, k, T;
31 modM[0] = 1;
32 /*求K! mod M,预处理,数组保存,备用。同余性质在此也得到应用*/
33 for(int i = 1; i <= 1000000; i++)
34 {
35 modM[i] = ((long long)modM[i - 1] * i) % M;
36 }
37 for(scanf("%d", &T); T; T--)
38 {
39 scanf("%d%d", &n, &k);
40 if(k == 0)
41 {
42 printf("1\n");
43 }
44 else printf("%d\n", (f(n, k) - f(n, k - 1) + M) % M);
45 }
46 return 0;
47}

 

时间复杂度分析:

1. 求幂模部分,由于其采用快速求模,对于每一组输入,时间复杂度为仅为O(log(N-K))

2.  取模采用打表法。时间复杂度为O(N),虽然比上者大,但是由于先预处理了,对运 行时时间限制影响不大。

排名主要根据运行时间,消 耗资源较少的主要是C++程序。同样的算法,用C++改写一下,主要是将f函数定义为内联函数,提交。时间减少了100MS

简单解释如下:在本实现中,f函数屡次 被调用。函数调用要有一定的时间和空间方面的开销,于是将影响其效率。特别是对于一些类似于f函数这样的函数,函数体代码不是很大,但又频繁地被调用,解决其效率问题更为重要。在使用C++编译时候,将f函数定义 为内联函数,在程序编译时,编译器将程序中出现的f函数的调 用表达式用f函数的函数体来进行替换。显然,这种做法不会产生转去转回的问 题,但是由于在编译时函数体中的代码被替代到程序中,因此会增加目标程序代码量,进而增加空间开销,而在时间开销上不象函数调用时那么大,可见它是以目标 代码的增加为代价来换取时间的节省。观察统计数据,也证明了这一点,代码长度从792B增长为826B。

posted @ 2010-11-03 20:36  Rockics  阅读(602)  评论(0编辑  收藏  举报