幂的求和取模

1.1 题目描述
春宵和秋锅比赛现农。
春宵说:我的农气值有: 这么大,你是不可能比我大的。

秋锅笑而不语。他在后面加了一个: (mod M) 。
然后,他问春宵:你的农气值现在是多少呢?
(好冷的题目。。)
1.2 输入格式
一行 3 个数,依次为M,K,N 。
1.3 输出格式
一行 1 个数,表示春宵的农气值。

1.4 样例输入
98 3 4
1.5 样例输出
2
1.6 数据范围
对于 20%的数据:N,M,K ≤ 10^3
对于 40%的数据:N,M ≤ 10^3,K ≤ 10^18
对于 80%的数据:M ≤ 10^5,N,K ≤ 10^18
对于 100%的数据:0 < M ≤ 3 × 10^6,N,K ≤ 10^18

 

我们可以发现直接计算1~n的k次方的和是不现实的,这时发现m的取值范围较小,然后打表找规律发现m为tkmod m的一个循环节。

于是我们只需用快速幂计算1~m的k次方取模的值就行了。

但是又不能对每一个数都做快速幂,我们可以发现合数的幂是由质数转来的,于是我们加上一个线性筛素数,只对素数做快速幂,在筛数的时候顺便转移tkmod m的值。

 1 program Neayo;
 2 const
 3         inf='sum.in';
 4         ouf='sum.out';
 5 var
 6         i,j,tot:longint;
 7         k,mo,n,ans,sum:int64;
 8         q:array[0..250000]of longint;
 9         a:array[0..3000000]of int64;
10         p:array[0..3000000]of boolean;
11 procedure init;
12 begin
13      assign(input,inf);assign(output,ouf);
14      reset(input);rewrite(output);
15      readln(mo,k,n);
16      close(input);
17 end;
18 function quickpower(num:int64):int64;
19 var tmp,time:int64;
20 begin
21      tmp:=1;time:=k;
22      while time>0 do
23      begin
24           if (time and 1)=1 then tmp:=(tmp*num)mod mo;
25           time:=time shr 1;
26           if tmp mod mo=0 then exit(0);
27           num:=(num * num)mod mo;
28      end;
29      exit(tmp mod mo);
30 end;
31 procedure go;
32 begin
33      a[1]:=1 mod mo;
34      sum:=a[1];
35      for i:=2 to mo do
36      if i<=n then
37      begin
38           if not p[i] then
39           begin
40                inc(tot);
41                q[tot]:=i;
42                a[i]:=quickpower(i);
43           end;
44           for j:=1 to tot do
45           begin
46                if i*q[j]>mo then break;
47                p[i*q[j]]:=true;
48                a[i*q[j]]:=(a[i]*a[q[j]]) mod mo;
49                if i mod q[j]=0 then break;
50           end;
51           sum:=(sum+a[i]) mod mo;
52      end
53      else break;
54      sum:=(sum*(n div mo))mod mo;
55      if n>mo then
56      begin
57           j:=n mod mo;
58           for i:=1 to j do
59           sum:=(sum+a[i])mod mo;
60      end;
61      writeln(sum mod mo);
62 end;
63 begin
64      init;
65      go;
66      close(output);
67 end.
posted @ 2012-11-04 21:58  neayo  阅读(452)  评论(0编辑  收藏  举报