HDU - 6189 Law of Commutation

Law of Commutation 

题目大意:给你n和a,问在【1,2n】中有多少个b满足 ab%m=ba%m,其中m=2n

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6189

解题思路:先打表,找一下规律

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll n,a;
ll qpow(ll a,ll b,ll m)
{
    ll ans=1;
    a=a%m;
    while(b)
    {
        if(b%2) ans=ans*a%m;
        a=a*a%m;
        b=b/2;
    }
    return ans;
}
ll qpow(ll a,ll b)
{
    ll ans=1;
    while(b)
    {
        if(b%2) ans=ans*a;
        b=b/2;
        a=a*a;
    }
    return ans;
}
int main()
{
    while(cin>>n>>a)
    {
            ll m=1<<n;
            ll ans=0;
            for(int i=1;i<=m;i++)
            {
                if(qpow(a,i,m)==qpow(i,a,m)) ans++;
            }
            cout<<ans<<endl;
    }
    return 0;
}

我们可以发现,当a为奇数的时候,答案永远是1,所以就需要讨论a是偶数的时候的情况

若a是偶数则ab也一定是偶数,所以b必须为偶数,则a=2*x ,ab=2b*xb,当b>=n的时候,ab

%m==0,所以可以找到当b<n的时候有多少符合题意的接,若b>=n,则ba%m==0,b=2x*y

ba=2ax*ya  %(2n)==0,则此时应使得ax>=n,x>=n/a,因此我们只需要计算出最小的x并求得在m的范围内

2x的倍数即可

 

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll n,a;
ll qpow(ll a,ll b,ll m)
{
    ll ans=1;
    a=a%m;
    while(b)
    {
        if(b%2) ans=ans*a%m;
        a=a*a%m;
        b=b/2;
    }
    return ans;
}
ll qpow(ll a,ll b)
{
    ll ans=1;
    while(b)
    {
        if(b%2) ans=ans*a;
        b=b/2;
        a=a*a;
    }
    return ans;
}
int main()
{
    while(cin>>n>>a)
    {
        if(a%2==1)
        {
            cout<<"1"<<endl;
            continue;
        }
        else
        {
            ll m=1<<n;
            ll ans=0;
            for(int i=1;i<=n;i++)
            {
                if(qpow(a,i,m)==qpow(i,a,m)) ans++;
            }
            ll b2=n/a;
            if(b2*a<n) b2++;
            ll b3=pow(2,b2);
            ll res1=m/b3-n/b3;
            cout<<ans+res1<<endl; 
        }
    }
    return 0;
}

 

猜你喜欢

转载自www.cnblogs.com/tombraider-shadow/p/12170992.html
今日推荐