就在昨天,笔者正在愉快的刷着牛客的比赛,然后,我遇到了这样一题
学长的白日梦
20级的学弟学妹们来了,实验室里可怜弱小又无助的wzc学弟终于变成了学长,可以压迫下一级了(?)。
但是wzc学长苦于自己的实力进步太慢,很担心自己在学弟学妹们面前丢人,所以天天熬夜在实验室里训练。
某一天wzc学长训练得实在太累了,居然在大白天做起了梦。
在梦里面,wzc学长在第一天有一个初始的码力值x,第二天的时候码力值变为了x2,第三天的时候码力值变为了x3......第i天的时候码力值变为了xi。
现在wzc学长想知道第i天的时候,他的码力值是多少。由于这个值可能非常大,请输出对9999999967取模的结果。
输入描述:
第一行一个整数T,代表输入数据组数。(1≤T≤1×103)
接下来T行,每行两个整数x和i,代表第一天的初始码力值,和所要求的是第几天的码力值。
(1≤x≤10,不会吧不会吧,不会真的有人这么弱吧)
(1≤i≤1×109)
输出描述:
输出T行,每行一个整数,代表xi对9999999967取模的结果。
示例1
输入
2
1 1000000000
2 3
输出
1
8
飞快的读完题,笔者心里暗喜,哈哈,这不就是考一个快速幂吗?(不会吧不会吧,不会真的有人还不会快速幂吧----->【快速幂】csdn博客)
然后,笔者自信爆棚的敲下了自认为完美的代码
#include<iostream>
#define ll long long
using namespace std;
ll n = 9999999967;
ll t;
ll qmi(ll x, ll i)
{
ll ans=1;
ll k = x%n;
while (i)
{
if (i & 1)
{
ans = ans *( k % n);
}
i >>=1;
k = k * k%n;
}
return ans;
}
int main()
{
cin >> t;
while (t--)
{
ll x, i;
cin >> x >> i;
cout << qmi(x, i) << endl;
}
return 0;
}
提交!然后…wa了?
喵喵喵????这怎么可能???!我取模的部分搞错了????
在辛辛苦苦debug1小时后,我发现了出题人的险恶用心…
n=9999999967,大于1e9.两个数对n取模后最大可能到1e20.然后,我们的long long小朋友就光荣的炸掉了。。。
啊这,咋回事啊!啥情况啊!那咋整啊?long long小朋友你hold住啊!!!!!!!!!TAT
唉,向大佬请教吧,然后,笔者顶着大佬的最长的手指头,学到了解决方法。快速乘!
快速乘实际上就是乘法,我们都知道,乘法的本质是加法,我们可以通过快速幂的思想比较轻松的写出快速乘的代码
#include<iostream>
#define ll long long
using namespace std;
const long long mod = 9999999967;
long long cheng(long long a, long long b) {
long long res = 0;
while (b)
{
if (b & 1) res = (res + a) % mod;
b >>= 1;
a = (a * 2) % mod;
}
return res;
}
long long ksm(long long a, long long b) {
long long res = 1;
while (b)
{
if (b & 1) res = cheng(res, a) % mod;
b >>= 1;
a = cheng(a, a) % mod;
}
return res;
}
int main()
{
int t;
cin >> t;
while (t--) {
long long ans;
long long x, i;
cin >> x >> i;
ans = ksm(x, i);
ans %= mod;
cout << ans << endl;
}
return 0;
}
和快速幂一样,快速乘也需要通过位运算来实现,然后把快速乘的代码用在快速幂里面。
那么接下来,我们需要解释一下为什么这样就可以不用炸long long小朋友了。首先,两个1e10的数相乘取模mod,是先得到一个1e20的数字然后再取模,当然,在我们得到1e20的时候,long long就已经炸掉了。而如果我们通过位运算改乘为加,对两个1e10的数字相加后再对mod取模,数据的大小一定会在long long的1e18之内。而这一题就是因为出题人恶心的把取模的数字设置成10位,就是用来卡你的普通快速幂。如果不想到快速乘的话是很难写出来的(当然快速加不是唯一的解题方法,不过…那种方法似乎更加变态TAT,在这里提一下吧,想学的小伙伴去看看 [ __int128_t]数据结构)
作者:Avalon Demerzel,是个正在不断努力学习的小白,如果觉得博客不错,就来个三连吧(点个赞也行)。让我们一起进步。