快速幂
用处
一个能快速求
nk%p的算法,在数论题目里可以用来模拟多次重复的运算,是数论的基础算法。
模板题
【题目描述】
求
nk%p的值。
【输入格式】
一行,包含三个数
n,k,p
【输出格式】
一行,输出
nk%p的值。
样例
样例输入
2 6 23
样例输出
18
样例说明
26=64,64%23=18
数据范围与提示
对于全部数据,
1≤n,k≤1015,1≤p≤109
解析
这是一道基本的数论题,不用数论算法就会超时(简单来说,不用数论思想就是暴力模拟)。
暴力模拟的时间复杂度为
O(k),但
k最大可以取
1015,肯定会超时。
快速幂是一种时间复杂度为
O(log2(k))的算法,这代表
k甚至可以取到
22×108(2200000000)。
可以说是无限了,C++中很难有这样的时间和内存够这种数运算了
(FFT也做不到呀
)。
为什么说快速幂时间复杂度为为
O(log2(k)),这因为它的算法模式。
利用
2进制来分治,将运算次数缩小到二分的次数。
比如数据
2 29 657
n=2,k=29,p=657
将
k转化成
2进制得
11101,ans=1
每次
n都会平方并进行取模,然后将
k÷2
因为
nk=(n×2)k÷2
但是
C语言中默认向下取整,所以
5÷2=2,但是还有个
1该怎么办呢?
所以为什么转化为
2进制,当
k%2=1,代表有一个
1是多出来的,要先把这
1个
a先乘上。
具体代码实现如下
#include
#include
using namespace std;
int n,k,p;
int ksm(int a,int b,int inf)
{
int ans=1;a%=inf;
while(b)
{
if(b&1)ans=ans*a%inf;
a=a*a%inf;b>>=1;
}
return 0;
}
int main()
{
scanf("%d%d%d",&n,&k,&p);
printf("%d
",ksm(n,k,p));
}
练习题 NOIP2013提高组day1【转圈游戏】
题目描述
n个小伙伴
(编号从
0 到
n−1)围坐一圈玩游戏。按照顺时针方向给
n个位置编号,从
0到
n−1。最初,第
0号小伙伴在第
0号位置,第
1号小伙伴在第
1号位置
,……,依此类推。
游戏规则如下:每一轮第
0号位置上的小伙伴顺时针走到第
m号位置,第
1号位置小伙伴走到第
m+1号位置
,……,依此类推,第
n−m号位置上的小伙伴走到第
0号位置,第
n−m+1号位置上的小伙伴走到第
1号位置
,……,第
n−1号位置上的小伙伴顺时针走到第
m−1号位置。
现在,一共进行了
10k轮,请问
x号小伙伴最后走到了第几号位置。
输入格式
输入共
1行,包含
4个整数
n,m,k,x,每两个整数之间用一个空格隔开。
输出格式
输出共
1行,包含
1个整数,表示
10k轮后
x号小伙伴所在的位置编号。
样例
样例输入1
10 3 4 5
样例输出1
5
数据范围与提示
对于
30%的数据
,0<k<7;
对于
80%的数据
,0<k<107;
对于
100%的数据
,1<n<106,0<m<n,1≤x≤n,0<k<109。