任意门
Problem Description
给 a,b ,每次 a,b 会变为 a+b,a−b ,问 k 次之后变成了哪两个数,对 998244353 取模,多组数据。
Input
第一行一个正整数 T(1≤T≤100000) ,代表测试组数。
接下来 T 行每行三个数 a,b,k(0≤a,b<998244353,0≤k≤109) 。
Output
T 行每行两个整数,代表每一组数据 a,b 最后变成了什么。
Sample Input
2
2 1 5
5 5 100
Sample Output
12 4
329904920 329904920
这一道题用到了取模的方法!接下来就来介绍一下吧!
-
取模问题往往是在所运算的结果过于庞大的情况下,整型已经无法储存,所以这个时候用到取模
-
但是我们取模的时候肯定不是(a+b)%p这样子来,因为a+b会造成溢出,所以,我们用以下公式:
-
(a + b) % p = (a%p + b%p) %p
(a - b) % p = ((a%p - b%p) + p) %p
(a * b) % p = (a%p)*(b%p) %p
快速幂算法模板1
typedef long long LL;
LL pow_mod(LL a,LL b,LL p){//快速幂取模
LL ans=1,base=a;
while(b>0){
if(b&1) //n%2==1
//判断是否是奇数,是奇数的话将多出来的数事先乘如sum
ans=ans*base%p;
base=base*base%p;
b>>=1;// b/=2
// 不断的两两合并再取模,减小a和b的规模
}
return ans;
}
1&1=1,其他的操作都为0
快速幂模板2
long long Mode(long long a, long long b, long long mode)
{
long long sum = 1;
while (b) {
if (b & 1) {
sum = (sum * a) % mode;
b--;
}
b /= 2;
a = a * a % mode;
}
return sum;
}
那么这里就是找规律,然后取模!
代码
#include <iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int mod=998244353;
long long _pow(long long a,long long b){
long long ans=1;
while(b){
if(b&1)ans=ans*a%mod;
b>>=1;
a=a*a%mod;
}
return ans;
}
int main() {
int n;
scanf("%d",&n);
while(n--){
long long a,b,k;
scanf("%lld%lld%lld",&a,&b,&k);
long long x,y,z=(k+1)/2-1;
if(k&1){
x=_pow(2,z)*(a+b)%mod;
y=_pow(2,z)*(a-b+mod)%mod;
}else{
x=2*_pow(2,z)*a%mod;
y=2*_pow(2,z)*b%mod;
}
printf("%lld %lld\n",x,y);
}
return 0;
}
感觉自己的转换成代码的能力比较弱,就是自己找到了规律之后,也要花一定的时间来转化成代码,不是很迅速,然后在取模的时候,取模也不是取得很好!望改进!