Remainder Calculator-指数循环结+欧拉函数

本文介绍了一种利用模幂运算和欧拉函数解决复杂数学问题的方法,并通过具体的算法实现展示了如何进行高效的模幂计算。文中给出了关键的数学公式,如a^b=a^(b%phi(c)+phi(c))(mod c),并提供了完整的C++代码实现。

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

耗时好久,终于把这个题目给做出来了,不容易啊,弱校的数学始终是硬伤啊~~~

公式:

a^b=a^(b%phi(c)+phi(c))(mod c);

phi(c)为1~c中,与c互质的数的个数。

((a^b)^c)=a^(b^c)

a^(b^c)=a^(b^c%phi(c)+phi(c)) (mod c);

b^c%phi(c)=b^(c%phi(phi(c))+phi(phi(c)));

#include<stdio.h>
#include<iostream>
#include<string.h>
#include<algorithm>
#include<queue>
#include<stack>
#include<map>
#include<string>
#include<stdlib.h>
#define INF_MAX 0x7fffffff
#define INF 999999
#define max3(a,b,c) (max(a,b)>c?max(a,b):c)
#define min3(a,b,c) (min(a,b)<c?min(a,b):c)
#define mem(a,b) memset(a,b,sizeof(a))
using namespace std;
struct node
{
    int u;
    int v;
    int w;
    bool friend operator < (node a, node b){
        return a.w < b.w;
    }
}edge[1001];
int gcd(int n,int m){if(n<m) swap(n,m);return n%m==0?m:gcd(m,n%m);}
int lcm(int n,int m){if(n<m) swap(n,m);return n/gcd(n,m)*m;}
int a[10001];
int b[10001];
int p[10001];
int phi(int x)
{
    int m;
    m=x;
    int i;
    for(i=2;i*i<=x;i++)
    {
        if(x%i==0)
        {
            m=m-m/i;
            while(x%i==0)x=x/i;
        }
    }
    if(x>1)
    m=m-m/x;
    return m;
}
int ex(int a,int b,int p)
{
    if(b==0)return 1%p;
    if(b==1)return a%p;
    int tx;
    tx=ex(a,b/2,p);
    tx=tx*tx%p;
    if(b%2==1)tx=tx*a%p;
    return tx;

}
int main()
{
    int T,i,j;
    int m,n;
    cin>>T;
    while(T--)
    {
        cin>>n>>m;
        for(i=0;i<n;i++)
        {
            cin>>a[i];
        }
        if(a[0]>=m)
        {
            puts("0");
            continue;
        }
        p[0]=m;
        for(i=1;i<n;i++)
        {
            p[i]=phi(p[i-1]);
        }
        for(i=n-1;i>=1;i--)
        {
            if(a[i]>=p[i])b[i]=p[i];
            else
            {
                int as=1;
                for(j=2;j<=a[i];j++)
                {
                    as*=j;
                    as=as%p[i];
                }
                if(i==n-1)
                {
                    b[i]=as+p[i];
                }
                else
                {
                    b[i]=ex(as,b[i+1],p[i])+p[i];
                }
            }
        }
        int as;
        as=1;
        for(i=2;i<=a[0];i++)
        {
            as*=i;
            as=as%m;
        }
        cout<<ex(as,b[1],m)<<endl;
    }
    return 0;
}












评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值