[NOIP模拟][数学推理]Math

本文探讨了一道关于模指数运算的问题,通过数学归纳法分析了a^b ≡ b^a (mod 2^n) 的解的数量。分为a为奇数和偶数两种情况进行讨论,并给出了解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目描述:
题目大意:
给定a,n(a≤109,n≤30),求有多少b(1≤b≤2n)满足:abba(mod2n)。多组数据。
样例输入

2
2 3
2 2

样例输出

3
2

题目分析
找规律加数学推理。首先分两种情况:
a为奇数:如果你打了个暴力,然后打打表什么的就可以发现答案恒为1。证明如下:
1、a为奇数,b也一定为奇数,否则,abba的奇偶性不同,就不可能同余2n
2、再证明ba(mod2n),利用数学归纳。
       ①奇数平方模8余1(你可以写成2n+12展开就能证明),所以有aba(mod8), 证明 ab8a2ka18(假设b=2k+1) (ak)2a8 1*a%8,即aba(mod8),同理bab(mod8),又因为题目中要求的是abba(mod2n) ,那么可得abba(mod8)(此步证明见最后),于是再综合前面两个得ab(mod8)
       ②奇数四次方模16余1,所以有abab4(mod16), 证明 ab16a4kab416(令b=4k+b%4) (ak)4ab416 1ab416,即abab4(mod16),同理baba4(mod16),又因为题目中要求的是abba(mod2n) ,那么可得abba(mod16),那么综合前面的可得ab4ba4(mod16),又因为abba(mod2n) ,那么可得abba(mod4),于是得ab(mod4),即a%4=b%4,所以得到ab(mod16)
        ③同理我们可得ab(mod32)
3、于是归纳得出满足要求的a,b满足条件ba(mod2n),又因为a,n确定,且1≤b≤2n,那么b就是唯一确定,即答案为1。
a为偶数:
1、同理b也一定为偶数。
2、若n≤b,则ab0(mod2n),因为题目要求abba(mod2n),故ba0(mod2n)。再设b=2kc (2kc)a2kaca0(mod2n),于是得n≤a*k na ≤k(向上取整),即2na整除2k 2na整除b,因为1≤b≤2n,所以n≤b的范围内,符合要求的b个数就是看2n内有多少个2na的倍数,即2n/2na(如果2na小于n,还需减去n以内2na的倍数的个数,即n/2na)。
3、若b<n,因为n≤30,暴力枚举加判断就行。
PS: 证明abba(mod2n)可推得abba(mod2k)k<n),abba(mod2n)ab=ba+2nx ab=ba+2kmabba(mod2k)
附代码

#include<iostream>
#include<cstring>
#include<string>
#include<cstdlib>
#include<cstdio>
#include<ctime>
#include<cmath>
#include<cctype>
#include<iomanip>
#include<algorithm>
#include<queue>
using namespace std;

int mi[50],t,n,a,ans,x;

int readint()
{
    char ch;int i=0,f=1;
    for(ch=getchar();(ch<'0'||ch>'9')&&ch!='-';ch=getchar());
    if(ch=='-') {ch=getchar();f=-1;}
    for(;ch>='0'&&ch<='9';ch=getchar()) i=(i<<3)+(i<<1)+ch-'0';
    return i*f;
}

int ksm(int  x,int y)
{
    int ret=1;
    for(;y;y/=2,x=(long long)(x*x)%mi[n])
        if(y&1) ret=(long long)(ret*x)%mi[n];
    return ret;
}

int main()
{
    //freopen("math.in","r",stdin);
    //freopen("math.out","w",stdout);

    mi[0]=1;
    for(int i=1;i<=30;i++)//预处理2的次幂
        mi[i]=(mi[i-1]<<1);
    t=readint();
    while(t--)
    {
        a=readint();n=readint();
        if(a%2==1) printf("1\n");
        else
        {
            ans=0;
            x=(n+a-1)/a;//相当于向上取整
            ans+=mi[n]/mi[x];
            ans-=n/mi[x];
            for(int i=2;i<=n;i+=2)
                if(ksm(a,i)==ksm(i,a)) ans++;
            printf("%d\n",ans);
        }
    }

    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值