1. 程式人生 > >HDU 6189 Law of Commutation 2017ACM-ICPC 廣西邀請賽 (打表找規律)

HDU 6189 Law of Commutation 2017ACM-ICPC 廣西邀請賽 (打表找規律)

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

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

For all test cases, you can assume that n30,1a109n≤30,1≤a≤109. OutputFor each test case, output an integer denoting the number of bb
Sample Input
2 3
2 2
Sample Output
1
2

 【題解】

 比賽時奇數推出來了偶數沒推出來,賊尬。。。

 賽後又琢磨了一陣,試了好幾遍才找到規律,打表。

 給定n和a,求1到(1<<n)範圍內滿足a^b = b^a的b的個數;

 打表後可以發現,如果a是奇數,再怎麼找也只有一個,而如果a是偶數,就要判斷了,b在[1,n]範圍內直接遍歷找,b>n時有很多偶數滿足條件,具體看程式碼:

 還有官方題解:

I Law of Commutation 
對於a為奇數的情況,b一定為奇數,下證b=a mod 2^n。 
由於奇數平方模8餘1,故a^b=a mod 8, b^a=b mod 8 
故a=b mod 8 


由於奇數四次方模16餘1,故a^b=a^(b%4) mod 16, b^a=b^(a%4) mod 16 
由於b%4=a%4,故a=b mod 16 
以此類推,得b=a mod 2^n。解唯一(當然打表可以看出來,現場一堆打表過的) 
對於a為偶數的情況,b一定為偶數。 
若b≥n,則a^b=0 mod 2^n,故b^a=0 mod 2^n。 
可直接求出b≥n時的個數。 
若b<n,則直接暴力,時間複雜度O(nloga)。

【AC程式碼】

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int N=31;
int m,n;

int mul_mod(int a,int b,int mod)//快速冪
{
    a%=mod;
    int x=1;
    while(b)
    {
        if(b&1) x= 1ll*a*x%mod;
        a = 1ll*a*a%mod;
        b >>= 1;
    }
    return x;
}

int main()
{
    int a;
    while(cin>>n>>a)
    {
        int maxn=(1<<n);
        if(a&1) puts("1"); 
        else
        {
            int ans=0;
            for(int i=2;i<=n;i+=2)
            {
                if(mul_mod(a,i,maxn) == mul_mod(i,a,maxn))
                    ans++;
            }

            int c=(n+a-1)/a; 
            int x=(1<<n) >> c;
            int t=n>>c;
            ans+=x;
            ans-=t;
            printf("%d\n",ans);
        }
    }
    return 0;
}