HDU 6189 Law of Commutation 2017ACM-ICPC 廣西邀請賽 (打表找規律)
阿新 • • 發佈:2019-01-30
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 ab≡ba (mod m).
InputThere 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 n≤30,1≤a≤109. OutputFor each test case, output an integer denoting the number of b.
Sample Input
Sample Output
由於奇數四次方模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)。
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 n≤30,1≤a≤109. OutputFor each test case, output an integer denoting the number of b.
Sample Input
2 3 2 2
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;
}