题目:http://acm.fzu.edu.cn/problem.php?pid=1759

也算是快速幂的一题了,只不过这里的指数B特别大。需要用到一个公式:

A^x = A^(x % Phi(C) + Phi(C)) (mod C),其中x≥Phi(C)

具体证明可见ac大神博客:http://hi.baidu.com/aekdycoin/item/e493adc9a7c0870bad092fd9。数论学得各种败笔和急于求成,自己的理解就不谈了~直接上代码就是直接用到公式即可:

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cmath>
 4 #include<algorithm>
 5 #include<cstring>
 6 using namespace std;
 7 char bb[1000005];
 8 __int64 euler(__int64 x){
 9     __int64 i, res = x;
10     for(i=2;i<(__int64)sqrt(x*10)+1;i++){//
11         if(x%i==0){
12             res = res /i *(i-1);
13             while(x%i==0) x/=i;
14         }
15     }
16     if(x>1) res = res/x*(x-1);
17     return res;
18 }
19 __int64 quickpow(__int64 m, __int64 n, __int64 k){
20     __int64 b = 1;
21     while(n>0){
22         if(n&1){
23             b = ((b%k)*(m%k))%k;
24         }
25         n = (n>>1);
26         m = ((m%k)*(m%k))%k;
27     }
28     return b;
29 }
30 int main(){
31     __int64 a, c, b, phic, sum;
32     int i, j, k, l;
33     while(~scanf("%I64d",&a)){
34         scanf("%s",bb);
35         scanf("%I64d",&c);
36         l = strlen(bb);
37         phic = euler(c);
38         if(l<=10){
39             b = bb[0]-'0';
40             for(i=1;i<l;i++){
41                 b = b*10 + (bb[i]-'0');
42             }
43             if(b<phic){
44                 printf("%I64d\n",quickpow(a,b,c));continue;
45             }
46         }
47         b = 0ll;   //求一个很大的数对一个数的模数的方法
48         for(i=0;i<l;i++){
49             b = b*10 + (bb[i]-'0');
50             while(b>=phic){   //while很重要!!!,防溢出
51                 b -= phic;
52             }
53         /*if(b>=phic){
54         b = b%phic;
55         }*/
56         }
57         printf("%I64d\n",quickpow(a,b+phic,c));
58     }
59     return 0;
60 }

还有一个09上海赛的题(hdu3221),大致也是那样思路做的,用的矩阵快速幂求的斐波那切数列,套用公式,当天写完之后wa了,过了几天后回来看,发现自己在矩阵快速幂的结构体变量中设的是int而不是long long,模板用的也一直是int,觉得不会超,后来改成long long就A了,结果证明还是超了。推出来的公式是:

n=1:a

n=2:b

n=3:ab

n=4:ab2

n=5:a2b3

n=6:a3b5

n=7:a5b8

n=8:a8b13

正常人应该都能看出规律了吧,就是斐波那切数列,由于指数比较大,要用到指数循环节的公式,中间用矩阵快速幂求斐波那切数列。具体代码:

View Code

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cmath>
  4 #include<algorithm>
  5 #include<cstring>
  6 #include<cmath>
  7 using namespace std;
  8 __int64 euler(__int64 x){
  9     __int64 i, res = x;
 10     for(i=2;i<(__int64)sqrt(x*10.0)+1;i++){
 11         if(x%i==0){
 12             res = res/i*(i-1);
 13             while(x%i==0) x/=i;
 14         }
 15     }
 16     if(x>1) res = res/x*(x-1);
 17     return res;
 18 }
 19 __int64 quickpow(__int64 m, __int64 n, __int64 k){
 20     __int64 b = 1;
 21     while(n>0){
 22         if(n&1){
 23             b = (b*m)%k;
 24         }
 25         n = (n>>1);
 26         m = (m*m)%k;
 27     }
 28     return b;
 29 }
 30 typedef struct{
 31     __int64 m[2][2];
 32 }Matrix;
 33 Matrix P = {0,1,1,1}, I = {1,0,0,1};
 34 Matrix matrixmul(Matrix a,Matrix b,__int64 p) //矩阵乘法
 35 {
 36        int i,j,k;
 37        Matrix c;
 38        for (i = 0 ; i < 2; i++)
 39            for (j = 0; j < 2;j++)
 40              {
 41                  c.m[i][j] = 0;
 42                  for (k = 0; k < 2; k++){
 43                      c.m[i][j] += (a.m[i][k] * b.m[k][j])%p;   // 取模的值
 44                  }
 45                  c.m[i][j] %= p;
 46              }
 47        return c;
 48 }
 49
 50 Matrix matrix_exp(Matrix P, Matrix I, __int64 n,__int64 p)
 51 {
 52        Matrix m = P, b = I;
 53        while (n >= 1)
 54        {
 55              if (n & 1)
 56                 b = matrixmul(b,m,p);
 57              n = n >> 1;
 58              m = matrixmul(m,m,p);
 59        }
 60        return b;
 61 }
 62 int main(){
 63     int i, j, k, l, t, T;
 64     __int64 a, b, p, n;
 65     __int64 f1, f2, f3, phip, aa, bb;
 66     scanf("%d",&T);
 67     for(t=1;t<=T;t++){
 68         scanf("%I64d%I64d%I64d%I64d",&a,&b,&p,&n);
 69         phip = euler(p);
 70         printf("Case #%d: ",t);
 71         if(n==1){
 72             printf("%I64d\n",a%p);continue;
 73         }
 74         if(n==2){
 75             printf("%I64d\n",b%p);continue;
 76         }
 77         if(n==3){
 78             printf("%I64d\n",((a%p)*(b%p))%p);continue;
 79         }
 80         f1 = 0; f2 = 1; k = 0;
 81         for(i=4;i<=n;i++){
 82             f3 = f1+f2;
 83             if(f3>=phip){
 84                 f3 %= phip;
 85                 k = 1;break;
 86             }
 87             f1 = f2; f2 = f3;
 88         }
 89         Matrix tmp;
 90         if(k){
 91             tmp = matrix_exp(P,I,n-3,phip);
 92             f1 = tmp.m[1][0]; f2 = tmp.m[1][1];
 93             aa = f2%phip+phip;
 94             f3 = f1+f2;
 95             bb = f3%phip+phip;
 96         }
 97         else{
 98             aa = f3;
 99             f3 = f1+f2;
100             bb = f3;
101         }
102         printf("%I64d\n",(quickpow(a,aa,p)*quickpow(b,bb,p))%p);
103     }
104     return 0;
105 }

最近的一道题就是前几天多校的题了,还是在那以后才会的这个公式,后来看了题解做的这题,那个trick也不是一般的坑人啊。

题意:给出三个数 (b, P and M),其中 ( 0<=b<P, 1<=P<=10^5, 1 <= M <=2^64 – 1 ),M的范围即暗示要用unsigned long long了,求满足nn!Ξb (mod p),(0≤n≤M)的n有多少个。也是大整数幂,其中指数很大,所以要用到之前说的指数循环节的公式

A^x = A^(x % Phi(C) + Phi(C)) (mod C),其中x≥Phi(C)

对于n!的处理,主要分为一下3部分处理:

1,n很小的时候,直接枚举就可以了,很小指的是n!<phip,此时上述公式也不适用;

2,公式适用要求x≥phip,此时nn!Ξnn!%phip+phipΞb (mod p),这样可以判断nn!Ξb (mod p)是否成立,但对于每一个n只是套用公式判断是否同余,仍然需要逐个枚举是否满足,而M特别大,枚举所有数必然超时;

3,可以进一步发现当某个n!%phip==0时,之后的所有n!都能整除phip,上述公式等价于nn!ΞnphipΞb (mod p),指数为固定值,这样就能看出循环节的公式了,根据乘法同余式(shit,这个也看了好久,phip个n相乘)nphipΞ(n%p)phipΞb (mod p),所以在枚举p个n就可以了,当其中某个n成立时,可以知道其后≤M的所有模p同余的数的个数,答案就出来了。(大trick见代码)

 1 #include<iostream>
 2 #include<cmath>
 3 #include<cstdio>
 4 #include<cstring>
 5 #include<algorithm>
 6 #define see(x) cout<<#x<<":"<<x<<endl;
 7 using namespace std;
 8 typedef unsigned __int64 LLU;
 9 LLU euler(LLU x){
10     LLU i, res = x;
11     for(i=2;i<(LLU)sqrt(x*10.0)+1;i++){
12         if(x%i==0){
13             res = res/i*(i-1);
14             while(x%i==0) x/=i;
15         }
16     }
17     if(x>1) res = res/x*(x-1);
18     return res;
19 }
20
21 LLU quickpow(LLU m, LLU n, LLU k){
22     LLU b = 1;
23     while(n>0){
24         if(n&1)
25             b = (b*m)%k;
26         n = n>>1;
27         m = (m*m)%k;
28     }
29     return b;
30 }
31 LLU f[100001];
32 int main(){
33     //freopen("1005.in","r",stdin);
34     //freopen("out.txt","w",stdout);
35     int t, T, i , k, l, flag;
36     LLU b, p, m, phip, ans;
37     scanf("%d",&T);
38     for(t=1;t<=T;t++){
39         ans = 0; flag = 0;
40         //cin>>b>>p>>m;
41         scanf("%I64u%I64u%I64u",&b,&p,&m);
42         if(b==0&&p==1&&m==18446744073709551615ull){
43             printf("Case #%d: 18446744073709551616\n",t);continue;
44         }//这里是个大trick,m==18446744073709551615就是2^64-1,如果b==0,p==1,即[0,m]里面所有的数模1都为0,所以一共有2^64个,而2^64已经超过了unsigned long long,所以要特判输出
45         phip = euler(p);
46         f[0] = 1;
47         if(b==0){
48             ans++;
49         }
50         for(i=1;i<=m;i++){
51             f[i] = f[i-1]*i;
52             if(f[i]>=phip){
53                 f[i] = f[i]%phip;
54                 flag = 1;
55                 if(f[i]==0){
56                     break;
57                 }
58             }
59             if(flag){
60                 if(quickpow(i,f[i]+phip,p)==b){
61                     ans++;
62
63                 }
64             }
65             else{
66                 if(quickpow(i,f[i],p)==b){
67                     ans++;
68                 }
69             }
70         }
71         for(k=0;i<=m&&k<p;i++,k++){
72             if(quickpow(i,phip,p)==b){
73                 ans = ans+1+(m-i)/p;
74             }
75         }
76         printf("Case #%d: %I64u\n",t,ans);
77         //cout<<ans<<endl;
78     }
79     return 0;
80 }

利用此题,亲测杭电oj,可以定义long long,只是输入输出不能用%lld,可以用cin,cout,如果用scanf,printf就只能用%I64d,所以要定义__int64。同long long也可以定义unsigned __int64,输入输出可以用%I64u。

关于数论题目的总结:

1,数论题目,代码不长,一般知道相关知识,即可求解,但是也要注意细节,以免大意失荆州~~

2,数学题目以后直接所有变量都设成long long吧,(:在这上面摔过很多次了

转载于:https://www.cnblogs.com/celia01/archive/2012/08/03/2621795.html

求 A^B mod C. (1=A,C=1000000000,1=B=10^1000000).(fzu1759,hdu3221,hdu4335)相关推荐

  1. 算法竞赛进阶指南--快速幂,求a^b mod p

    // 快速幂,求a^b mod p int power(int a, int b, int p) {int ans = 1;for (; b; b >>= 1) {if (b & ...

  2. 第M题 快速幂详解!: 给出3个正整数A B C,求A^B Mod C。

    给出3个正整数A B C,求A^B Mod C. 例如,3 5 8,3^5 Mod 8 = 3. Input 3个正整数A B C,中间用空格分隔.(1 <= A,B,C <= 10^9) ...

  3. C语言学习之求∑k(k=100)+∑K*k(k=50)+∑1/k(k=10)

    求∑k(k=100)+∑K*k(k=50)+∑1/k(k=10) #include <stdio.h> #include <math.h> void main(){double ...

  4. C语言试题九十一之写一个程序,用公式π/4=1-1/3+1/5-1/7+...,求π的近似值,直到最后一项的绝对值小于10^-8为止。

    1.题目 写一个程序,用公式π/4=1-1/3+1/5-1/7+...,求π的近似值,直到最后一项的绝对值小于10^-8为止. 2 .温馨提示 C语言试题汇总里可用于计算机二级C语言笔试.机试.研究生 ...

  5. 用公式π/ 4 = 1 – 1 / 3 + 1 / 5 – 1 / 7 + … 求π的近似值,直到最后一项的绝对值小于10的负6次方为止。

    用公式π/ 4 = 1 – 1 / 3 + 1 / 5 – 1 / 7 + - 求π的近似值,直到最后一项的绝对值小于10的负6次方为止. C源代码: #include <stdio.h> ...

  6. 我的世界mod整合包java_我的世界1.10.2mod大全+整合包+合集

    我的世界1.10.2mod大全汇集了相关版本的大量的实用mod和资源整合包,对于玩家的游戏所需非常有帮助,大家可以一起激情战斗,在梦幻般的神秘世界开展全新的冒险之旅,在建造的时候也更加方便,特备是红石 ...

  7. MC仿JAVA版背包界面_Minecraft背包编辑器mod下载大全(1.5.2-1.7.10)

    详细介绍: All--U--Want 让新手们更好地了解一下这个Mod的神奇之处 Mod功能 可以设置某物品无限耐久 调节某物品攻击力 调节物品附魔属性,级别不限 附魔书的修改 药水效果设置 头颅制作 ...

  8. C语言-用π/4=1-1/3+1/5-1/7+1/9-...公式求π的近似值求π的近似值,直到最后一项的绝对值小于10^6为止。

    #include<stdio.h> #include<math.h> main() {int s;float n,t,pi;t=1.0;pi=0;n=1.0;s=1;while ...

  9. 求∑(k=1~100)k+∑(k=1~50)k2+∑(k=1~10)

    这个算很简单的题,就是有规律的累加. 如果要考虑输出小数的话,将int换成float或double,输出也需要修改 我犯了特傻的两个错,一个是以为n只能一个循环用一个,其实只要修改对它的限制,没有特定 ...

最新文章

  1. API和schema开发过程问题汇总
  2. Hello Shell
  3. Docker 容器技术 — Image
  4. 【AI白身境】一文览尽计算机视觉研究方向
  5. Nginx的Gzip模块配置指令(三)
  6. 开发板实现645协议C语言,迅为-imx6ull开发板之C语言实现LED例程
  7. 函数调用过程简单分析
  8. 2019中兴捧月之智能音频处理参赛总结
  9. echarts 动态设置标题_echart动态生成标题
  10. vue NoData
  11. java 同步块_java 同步块(Java Synchronized Blocks)
  12. Linux16.04与win10搭建samba服务器
  13. 阶段3 2.Spring_02.程序间耦合_2 编译期依赖
  14. [Android Pro] 组件化:企业级大型项目必经之路
  15. 下载Eclipse IDE
  16. cpu顶盖怎么看步进_硬核科普丨什么是CPU步进?B0步进和U0步进具体差别有哪些...
  17. 读入一系列正整数数据,输入-1表示输入结束,-1本身不是输入的数据。程序输出读到的数据中的奇数和偶数的个数。
  18. intel网卡驱动for linux ubuntu系统
  19. 正确处理闲置报废的电子垃圾
  20. APP - IOS_Application 常用推荐

热门文章

  1. 基于 Bochs 的操作系统内核实现
  2. 后台开发经典书籍--代码大全
  3. web服务器测试web bench
  4. saltstack管理saltstack认证相关
  5. 专访 | 德国大神Hans Uszkoreit:语言才是AI的关键,深度学习无法解决NLP的核心问题...
  6. Json 不同语言的使用
  7. S2SH整合所需jar包及其详解
  8. Android开源项目第二篇——工具库篇
  9. SVN关于忽略xcuserdata目录
  10. Erlang列表操作里面的变量绑定规则