A ^ B mod C. (1 < = A, C < = 10000000000, 1 < = B < = 10 ^ 1000000) 를 구하 십시오. (fzu 1759, hdu 3221, hdu 4335)

37166 단어 HDU
제목: 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
",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
",quickpow(a,b+phic,c)); 58 } 59 return 0; 60 }

그리고 09 상하 이 경기 의 문제 (hdu 3221) 도 대체적으로 그렇게 생각 하고 만 들 었 습 니 다. 행렬 의 빠 른 속도 로 구 하 는 피 보 나 절 수열 을 사용 하고 공식 을 사용 합 니 다. 그날 다 쓴 후에 wa 가 되 었 습 니 다. 며칠 후에 돌아 와 보 니 자신 이 행렬 의 빠 른 속도 의 구조 체 변수 에 롱 롱 롱 이 아니 라 int 를 설정 한 것 을 발 견 했 습 니 다. 템 플 릿 도 int 를 사용 해서 초과 하지 않 을 것 이 라 고 생각 합 니 다.나중에 롱 롱 롱 이 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
",a%p);continue; 73 } 74 if(n==2){ 75 printf("%I64d
",b%p);continue; 76 } 77 if(n==3){ 78 printf("%I64d
",((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
",(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 을 사용 해 야 한 다 는 것 을 암시 합 니 다. nn 을 만족 시 키 세 요!Ξb (mod p), (0 ≤ n ≤ M) 의 n 은 몇 개 입 니까?또한 큰 정수 멱 으로 그 중에서 지수 가 매우 크기 때문에 앞에서 말 한 지수 순환 절의 공식 을 사용 해 야 한다.
A ^ x = A ^ (x% Phi (C) + Phi (C)) (mod C), 그 중 x ≥ Phi (C)
n 에 대해!의 처 리 는 주로 세 부분 으로 나 뉜 다.
1, n 아주 어 렸 을 때, 직접 매 거 하면 됩 니 다. 아주 작은 것 은 n 입 니 다! 2, 공식 적용 요구 x ≥ phip, 이때 nn!Ξnn!%phip+phipΞb (mod p), 이렇게 하면 nn 을 판단 할 수 있 습 니 다!Ξb (mod p) 가 성립 되 었 는 지 여 부 는 알 수 있 지만 모든 n 에 대해 공식 적 으로 동 여 부 를 판단 할 뿐 일일이 만족 하 는 지 여 부 를 매 거 해 야 한다. M 은 매우 크 고 매 거 진 모든 수 는 반드시 시간 을 초과 할 것 이다.
3, 어떤 n 이 되 는 것 을 더 발견 할 수 있 습 니 다!%phip = = 0 시, 그 후의 모든 n!모두 phoip 을 제거 할 수 있 습 니 다. 상기 공식 은 N 과 같 습 니 다!Ξ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
",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
",t,ans); 77 //cout<<ans<<endl; 78 } 79 return 0; 80 }

이 문 제 를 이용 하여 항 저 우 전기 oj 를 직접 측정 하면 long long 을 정의 할 수 있 습 니 다. 입 출력 만% lled 를 사용 할 수 없고 cin, cout 를 사용 할 수 있 습 니 다. scanf 를 사용 하면 printf 는% I64d 만 사용 할 수 있 기 때문에int64。long long 과 함께 unsigned 를 정의 할 수 있 습 니 다.int 64, 입 출력 은% I64u 를 사용 할 수 있 습 니 다.
수론 문제 에 대한 총 결:
1. 수론 문제, 코드 가 길지 않 습 니 다. 일반적으로 관련 지식 을 알 고 있 으 면 구 해 낼 수 있 습 니 다. 그러나 부주의 로 형 주 를 잃 지 않도록 디 테 일 에 도 주의해 야 합 니 다 ~ ~
2. 수학 문제 이후 모든 변 수 를 long 으로 설정 합 시다.
 
 

좋은 웹페이지 즐겨찾기