题目链接:【深蓝】教科书般的亵渎
"现在给大家展示一波教科书般的亵渎" "扭了扭了"
炉石传说是一款比较火的卡牌游戏,不同的卡牌间可以打出许多不可思议的配合。
炉石传说的战斗大部分由随从来完成。每个随从都有血量。当随从血量为0时,随从就会死亡。
"恐怖的奴隶主"是一个有3血的随从。他的特效是:每当该随从收到伤害且没有死亡时,召唤一个恐怖的奴隶主。也就是说,一个3血或2血的奴隶主,受到1点伤害后,都会召唤一个新的3血的奴隶主。而一个1血的奴隶主如果受到了1点伤害,就会直接死亡而不会召唤奴隶主。
"亵渎"是一张法术牌。其效果是:对全场随从造成1点伤害,如果有随从被亵渎的伤害打死,就再次施放亵渎。如果场上有一个1血一个2血的随从,亵渎会对全场打1,杀死那个1血随从,再全场打1,杀死那个2血的随从,再对全场打1(虽然此时场上已经没有随从了)
可以看出,奴隶主和亵渎的效果都是递归定义的。两张牌只要配合起来,就可能造成无限的递归。炉石的程序员肯定不希望游戏发生这种情况,他们偷偷给亵渎加了一个使用次数限制,亵渎在自我递归一定次数后就会停止了。
现在,假设你是一个炉石主播。你的场上有a1a1个1血的奴隶主,a2a2个2血的奴隶主,a3a3个3血的奴隶主,亵渎在释放nn次后就会停止递归。游戏中随从的数量不做限制,可以同时有无限个随从出现在游戏里。现在你释放了一次亵渎,游戏陷入了漫长的结算过程。这个时候,不断地有弹幕在问你:"主播主播,一共死了多少个奴隶主啊?"你决定用你高超的编程技术来回答这个问题。
Input
输入共一行。这一行包括四个数 a1,a2,a3,n(0≤a1,a2,a3≤109,2≤n≤1018)a1,a2,a3,n(0≤a1,a2,a3≤109,2≤n≤1018)分别表示1血奴隶主的个数、2血奴隶主的个数、3血奴隶主的个数、亵渎的最大释放次数。
Output
输出共一行,包含一个整数(对109+7109+7取模) ,表示死掉奴隶主的个数。
Examples
Input
1 1 1 4
Output
5
Input
1 0 1 5
Output
1
思路:
可知第一回合之后a1的数量都为上一回合的a2,a2的数量为上回合的a3,a3的数量为上回合的a2+a3……
又知斐波那契数列求和公式,即Sn = fib(n+2)-1
所以此题解为a1 + fib(n-1)*a2 + (fib(n)-1)*a3
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
ll MOD = 1e9+7;
ll a1,a2,a3,n;
struct sq{
ll sq[2][2];
void mes(){
memset(sq,0,sizeof(sq));
}
};
sq operator *(sq a,sq b){
sq tmp;
tmp.mes();
for(int i=0;i<2;i++){
for(int j=0;j<2;j++){
for(int k=0;k<2;k++){
tmp.sq[i][j]=(tmp.sq[i][j]+a.sq[i][k]*b.sq[k][j])%MOD;
}
}
}
return tmp;
}
ll fi(ll n){
sq ans,m;
ans.mes();
m.mes();
m.sq[0][0]=m.sq[0][1]=m.sq[1][0]=1;
m.sq[1][1]=0;
ans.sq[0][0]=ans.sq[1][1]=1;
ans.sq[0][1]=ans.sq[1][0]=0;
while(n){
if(n&1){
ans=ans*m;
}
m=m*m;
n>>=1;
}
return ans.sq[0][1]%MOD;
}
int main(){
cin>>a1>>a2>>a3>>n;
if(a1 && a2 && a3)
{
if(n == 2)
{
cout<<(a1%MOD + a2%MOD)%MOD<<endl;
}
else if(n == 3)
{
cout<<(a1%MOD + a2%MOD + a3%MOD)%MOD<<endl;
}
else
{
ll b1 = fi(n-1);
ll b2 = fi(n)-1;
//cout<<b1<<" "<<b2<<endl;
ll ans = (a1%MOD + (a2%MOD*b1)%MOD + (a3%MOD*b2)%MOD)%MOD;
cout<<ans<<endl;
//cout<<(a1%MOD + (a2%MOD)*(fi(n-1)%MOD)%MOD +((fi(n)-1)%MOD *(a3%MOD))%MOD )%MOD;
}
}
else if(a1 == 0)
{
cout<<0<<endl;
}
else if(a2 == 0)
{
cout<<a1%MOD<<endl;
}
else if(a3 == 0)
{
cout<<(a1%MOD+a2%MOD)%MOD<<endl;
}
return 0;
}