题目链接:https://ac.nowcoder.com/acm/contest/66594/D
这题题意很简单这里就不加赘述了,直接开始!
这题呢有两种做法,一种是直接计算,另一种是运用扩展欧拉定理来进行运算。
第一种比较简单我就直接贴代码了,就是直接计算嘛(我是傻子,第一次做的时候我没想到wuwuwu)。
#include <bits/stdc++.h>
using namespace std;
#define int long long
signed main()
{
int i, j;
int n, p;
int ans = 2;
cin >> n >> p;
for (i = 0; i < n; i++)
{
ans = (ans * ans) % p;
}
cout << ans << endl;
system("pause");
return 0;
}
接下来就是重头戏,也就是第二种做法,扩展欧拉定理(这里证明就不给出喽)
让我们先来了解一下什么是欧拉定理,如图
看不懂?(强行看不懂),没关系,让我们来解释一下这个式子,a和m的最大公因数为一,这代表什么呢?当然是a和m互质啦,至于φ(m)指的就是小于m的与m互质的数的个数(欧拉函数)
完整的意思呢,就是如果a与m互质,则a的小于m的与m互质的数的个数次方模m==1.
好,简单了解了欧拉定理之后,让我们来看一下扩展欧拉定理
相信在看了上面的句子之后看懂这个式子应该挺容易的,只不过不清楚里面的变量名是啥意思,简单来说就是a的b次方模m(很简单吧)。再切回题目,这个定理完美的贴合题意,对吧。不多说啥了,上代码,代码见真章!
#include <bits/stdc++.h>
using namespace std;
#define int long long//十年int两茫茫,不思long,自难忘
int euler(int n)//欧拉函数
{
int i;
int res = n, a = n;
for (i = 2; i <= a / i; i++)//求质因数,把有相同质因数的数删掉
{
if (a % i == 0)
{
res = res / i * (i - 1);//这种写法有效防止溢出
while (a % i == 0)
{
a /= i;
}
}
}
if (a > 1)
res = res / a * (a - 1);
return res;
}
int quickpow(int x, int y, int z)//快速幂,不取模的话会爆
{
int result = 1;
while (y != 0)
{
if (y & 1)
result = (result * x) % z;
x = (x * x) % z;
y >>= 1;
}
return result;
}
signed main()
{
int n, p;
cin >> n >> p;
int x = euler(p);
if (quickpow(2, n, x) < x)//扩展欧拉定理
{
cout << quickpow(2, quickpow(2, n, x), p) << endl;
}
else
{
int a = quickpow(2, n, x);
a += x;
cout << quickpow(2, a, p) << endl;
}
system("pause");
return 0;
}
愉快的算法之旅到这就结束啦,你是不是又学废了[滑稽]。