HDU - 6189 Law of Commutation(找规律,推公式)

As we all know, operation ''+'' complies with the commutative law. That is, if we arbitrarily select two integers a and b, a+b always equals to b+a. However, as for exponentiation, such law may be wrong. In this problem, let us consider a modular exponentiation. Give an integer m=2n and an integer a, count the number of integers b in the range of [1,m] which satisfy the equation abba (mod m
).
Input There are no more than 2500 test cases.

Each test case contains two positive integers n and a seperated by one space in a line.

For all test cases, you can assume that n30,1a109. Output For each test case, output an integer denoting the number of b.
Sample Input
2 3
2 2
Sample Output
1
2


a为奇数,则ab mod m为奇数,若b为偶数,则ba mod m为偶数,矛盾,故b

为奇数

对于一个奇数x=2k+1

x2=4k2+4k+1=4k(k+1)+1,进而 x21(mod 23)x2=8k+1x4=(8k+1)2=64k2+16k+1,进而 x41(mod 24),以此类推有 x2y1(mod 2y+2)

aba(mod 23),bab(mod 23)

ab(mod 23)

abab%4(mod 24),baba%4(mod 24)

,且 a%4=b%4,故有 ab(mod 24)

(b,24)=1

,故 b在模 24意义下有逆元 b1,进而有 (ab1)x1(mod 24),其中 x=a%4为奇数,由于 x|ϕ(24)=23,故有 ab11(mod 24),即 ab(mod 24)

以此类推得ab(mod 2n)

,即b=a%m,这说明解至多一个,而显然aaaa(mod m),故解唯一

a为偶数时怎么算,m一定为偶数,所以a^b%m的结果也为偶数,那么b^a%m的结果也必须为偶数,所以b必须为偶数,a既然为偶数那么一定可以写成2*x,所以a^b=2^b*x^b,又m=2^n显然可以发现如果b>=n那么a^b%m一定为0,这个时候就可以分类讨论,由于题目数据中n非常小,所以b<n时直接暴力求解,那么b>=n时这个已经确定a^b%m=0所以我们需要b^a%m同样为0,b为偶数,那么b一定可以表示为2^x*y,那么b^a=2^ax*y^a,我们先令y取得最小1,b^a=2^ax,b^a(2^ax)%m(2^n)=0,所以ax>=n,x>=n/a(注意这里n/a应该向上取整),所以我们就这样找到最小满足条件的x,然后在求出m以内2^x的倍数即可(注意把n以内的答案减去,因为n以内的答案暴力时求过一遍)

以上借鉴的都是别的大佬的题解,实在数学差,智商被碾压。看了好久才有那么一点思路。

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
typedef long long LL;
using namespace std;
LL bp(LL a,LL b,LL m)
{
    if(b==0) return 1;
    if(b%2==1) return a*bp(a,b-1,m)%m;
    else {
        LL mul=bp(a,b/2,m);
        return mul*mul%m;
    }
}
int main()
{
    LL a,m,ans;
    int n;
    while(scanf("%d %lld",&n,&a)!=EOF){
            m=1<<n;
            ans=0;
        if(a&1) printf("1\n");
        else {
            for(LL i=1;i<=n;i++){
                if(bp(a,i,m)==bp(i,a,m)){
                    ans++;
                }
            }
            LL b2=1<<((n-1)/a+1);
            ans=ans+(m/b2-n/b2);
            printf("%lld\n",ans);
        }
    }
    return 0;
}


猜你喜欢

转载自blog.csdn.net/sinat_40948489/article/details/80422381