您的位置:首页 > 其它

CSU 1769: 想打架吗?算我一个!所有人,都过来!(3)

2016-07-27 16:07 239 查看
题目:

CSU 1723: 想打架吗?算我一个!所有人,都过来!

CSU 1767: 想打架吗?算我一个!所有人,都过来!(2)


Description

现在《炉石传说》这款卡牌游戏已经风靡全球。2015年加入环境的“黑石山的火焰”扩展带来了一个新套牌的核心卡片“恐怖的奴隶主”,而这套统治游戏的套牌叫做“奴隶战”。“恐怖的奴隶主”的登场音效“想打架吗?算我一个!”一定在所有这个时代的《炉石传说》玩家心里留下来难以磨灭的印象。

“恐怖的奴隶主”是一个有3点生命值的生物,当其在场上受到非致命伤害时(如3点生命值的奴隶主受到1点或2点伤害时,或者2点生命值的奴隶主受到1点伤害时)会召唤一个新的3点生命值的“恐怖的奴隶主”,受到致命伤害(伤害大于等于现有生命值)时则会直接死去。另外一类卡片可以使全部生物造成1点伤害(降低1点生命),被称为“旋风斩效果”。因此“恐怖的奴隶主”,在场上经过多次“旋风斩效果”就可能由一个变成很多个,同时发出那个令人恐惧的声音“所有人,都过来!”。

另一方面,《炉石传说》规定,场上最多存在7个生物,这极大地限制了“恐怖的奴隶主”“越生越多”。当一次“旋风斩效果”发生时,优先处理受到非致命伤害的“恐怖的奴隶主”,召唤新的“恐怖的奴隶主”,直到生物数量达到7个不再继续召唤新的“恐怖的奴隶主”,然后清除掉生命值降为0或0以下的“恐怖奴隶主”。如场上有7个生命值为1的“恐怖的奴隶主”,则一次“旋风斩效果”后场上有0个“恐怖的奴隶主”。又如,场上有6个生命值为3的“恐怖的奴隶主”,则一次“旋风斩效果”后场上有6个2点生命的“恐怖的奴隶主”以及1个3点生命的“恐怖的奴隶主”。又如,场上有4个1点生命的“恐怖的奴隶主”以及2个2点生命的“恐怖的奴隶主”,则一次“旋风斩效果”后场上有2个1点生命的“恐怖的奴隶主”以及1个3点生命的“恐怖的奴隶主”。

在本系列题目2中我们已经知道了如何计算多个“恐怖的奴隶主”在经历n次旋风斩效果后会剩下多少。现在游戏出现了bug,场上奴隶主的个数不再受到7个的上限限制了。场上剩下了一些1点生命,一些2点生命,一些3点生命的奴隶主,现在问这些奴隶主经过n次旋风斩效果,场面会变成什么样子。


Input

有多组数据。

每组数据一行,hp1,hp2,hp3,n(0<=hp1,hp2,hp3<=10^9,0<=n<=10^6)

分别代表1点生命,2点生命,3点生命的奴隶主个数,以及之后旋风斩次数。


Output

每组用一行输出最终总的奴隶主个数(结果对1000000007取模),格式见样例。


Sample Input

1 1 1 3
3 3 3 2


Sample Output

10
18

看到这个题目,第一感觉自然是斐波那契数列。

如果斐波那契的第n项和第n+1项是c和d,那么答案就是

t1 = c*h2 % 1000000007;

t2 = d*h3 % 1000000007;

printf("%d\n", (t1 + t2) * 2 % 1000000007);

关键就是求c和d

如果n的非常非常大,那么斐波那契数列肯定会出现2个相邻的数x,y,x和y都大于1,但是与1模1000000007同余

如果这个x和y出现的比较早,比如前1000的位置,那么n可以等价成1000内的某个数。

可惜,事实上我真的去算过x和y的位置,是在第1000000007*2和第1000000007*2+1项的位置。

这让我想起来好像以前做过这个题目,就是求斐波那契数列的某一项除以1000000007的余数,可惜不记得在哪做的了。

之所以想起来这个是因为我想起来1000000007是1个质数(确实是的)。

这应该是斐波那契数列的性质吧,我就不深究了。(好懒的作者)

如果n是比1000000007大好多的数,第一步就是利用这个循环的规律把n变小。

这个题目n要小很多,这个步骤就省略了。

然后到底怎么求c和d呢?

要用到矩阵快速幂,也就是用二分递归的方法,求出一个矩阵的高次幂。

这个题目很多地方都要注意越界的问题,有趣的是,1000000007刚好接近int值的最大值的一半

代码:

#include<iostream>
using namespace std;

long long a, b, c, d;
long long x1, x2, x3, x4;

void f(int n)
{
if (n == 0)
{
a = 1;
b = 0;
c = 0;
d = 1;
return;
}
f(n / 2);
x1 = a*a + b*c;
x2 = (a + d)*b;
x3 = (a + d)*c;
x4 = b*c + d*d;
a = x1 % 1000000007;
b = x2 % 1000000007;
c = x3 % 1000000007;
d = x4 % 1000000007;
if (n % 2)
{
c += a;
a = c - a;
d += b;
b = d - b;
}
}

int main()
{
int h1, h2, h3, n;
long long t1, t2;
while (scanf("%d %d %d %d", &h1, &h2, &h3, &n) != EOF)
{
f(n);
t1 = c*h2 % 1000000007;
t2 = d*h3 % 1000000007;
printf("%d\n", (t1 + t2) * 2 % 1000000007);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: