UPC Contest2394 - 2020年春混合个人训练第八场问题 A: 埃匹希斯水晶
题目描述
⼤家都知道,卡德加是⼀个神奇的法师。
有⼀天,他发现了⼀种可以作⽤在埃匹希斯⽔晶上的魔法:在左右两个祭坛上放⼀定量的⽔晶,然后施放⼀个法术,左边⼀堆的⽔晶数量会变成原来两个祭坛上⽔晶之和,右边⼀堆会变成两个祭坛上⽔晶数量之差。
卡德加现在有两堆⽔晶,分别有A个和B个。他打算集中精⼒连续释放N次法术,但不知道最后能拿到多少⽔晶,于是他找到了要塞指挥官(就是你了)。
输入
三个整数A,B,N(A,B≤109,N≤1018),表⽰祭坛上刚开始的⽔晶数,和法术的释放次数。
输出
两个数,祭坛上最后的⽔晶数。输出模(109+7)。
样例输入 Copy
1 2 3
样例输出 Copy
6 2
先放一个暴力代码:
while(n--)
{
ll tmp=a;
a=a+b;
b=abs(tmp-b);
cout<<a<<" "<<b<<endl;
}
这道题比较神奇,看着题目模拟的话,反正我是没能模拟出来,然后就打了个暴力的枚举法,随便找两个数,全都列出前十项进行了一波观察,一看,巧妙啊,果然有规律可循,注意奇偶的情况,比如说就那上图的第一个例子来说,奇数行,第一行左侧的值等于(2+3)×20,第三行左侧的值,(2+3)×21,第五行(2+3)×22,如果n是奇数,那么就可以根据上述规律推出左侧的值,,偶数的时候,也是相同的情况,只不过一开始的那个数是(2+3)+abs(2-3);接着再来找右侧值得规律,神奇的发现,规律也是一样的,也是只改变了一开始的那个基数;右侧奇数项一开始的那个数是abs(3-2),偶数项的话,一开始的那个数是(3+2)-abs(3-2);
接下来就请看代码吧:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod=1e9+7;
ll qpow(ll q,ll x,ll y)
{
ll res=q;
while(y)
{
if(y%2!=0)
{
res=res*x%mod;
y--;
}
x=x*x%mod;
y/=2;
}
return res;
}
int main()
{
ll a,b,n;
ll ans1=0,ans2=0;
scanf("%lld%lld%lld",&a,&b,&n);
ll tmp1=a+b+(abs(a-b));//偶数情况
//计算左侧的值
if(n&1)
{
ll cnt=n/2+1;//第几个奇数
ans1=qpow(a+b,2,cnt-1);
}
else
{
ll cnt=n/2;//第几个偶数
ans1=ans1=qpow(tmp1,2,cnt-1);
}
//计算右侧的值
if(n&1)//奇数
{
ll cnt=n/2+1;
ans2=qpow(abs(a-b),2,cnt-1);
}
else//偶数
{
ll cnt=n/2;
ans2=qpow(abs(a+b-abs(a-b)),2,cnt-1);
}
printf("%lld %lld\n",ans1,ans2);
return 0;
}
/*
while(n--)
{
ll tmp=a;
a=a+b;
b=abs(tmp-b);
cout<<a<<" "<<b<<endl;
}
*/