[规律] Jzoj P4222 恐怖的奴隶主

Description

在《炉石传说》这款游戏中,有一张随从卡牌叫做“恐怖的奴隶主”。这张卡牌的描述是这样的:每当该随从受到伤害且没有死亡,召唤另一个恐怖的奴隶主。还有一张卡牌叫做“旋风斩”,描述是“对所有随从造成1点伤害”。使用“旋风斩”后,生命值变为0的“恐怖的奴隶主”并不会立即死亡,而会先结算召唤新的“恐怖的奴隶主”再结算生命值为0的“恐怖的奴隶主”的死亡。当然,使用旋风斩后,生命值变为0的“恐怖的奴隶主”不会召唤新的“恐怖的奴隶主”。随从的数量是有上限的,在召唤一个随从前如果随从数量已经达到上限则不会召唤。现在,如果随从数量上限为k,最开始只有一个生命值为m的“恐怖的奴隶主”,而且新召唤出来的“恐怖的奴隶主”的生命值也是m,那么使用了n张“旋风斩”后还有多少个“恐怖的奴隶主”呢?
 

Input

输入共一行包含3个正整数n, m, k。

Output

输出共一行包含1个整数,表示使用n张旋风斩后“恐怖的奴隶主”的数量。
 

Sample Input

4 3 7

Sample Output

6
【样例说明】
初始有1个生命值为3的“恐怖的奴隶主”。
第1次旋风斩后,召唤了1个“恐怖的奴隶主”,剩余1个生命值为2的和1个生命值为3的。
第2次旋风斩后,召唤了2个“恐怖的奴隶主”,剩余1个生命值为1的、1个生命值为2的和2个生命值为3的。
第3次旋风斩后,召唤了3个“恐怖的奴隶主”,然后1个生命值为0的死亡,剩余1个生命值为1的、2个生命值为2的和3个生命值为3的。
第4次旋风斩后,试图召唤5个“恐怖的奴隶主”,但随从数量达到上限7,所以只召唤了1个,然后其中1个生命值为0的死亡,最后剩余2个生命值为1的、3个生命值为2的和1个生命值为3的,共6个。
 

Data Constraint

对于10%的数据,n,k<=10^3;
另有15%的数据,n,m<=10^5;
另有25%的数据,m<=10^5;
另有20%的数据,10^8<=n,m,k<=10^9;
对于全部数据,n,m,k<=10^15。

 

题解

  • 这显然就是个找规律的题目,让我们来看一组数据
  • 6 20 
    2 4 8 16 20 19 19 18 16 12 16 20 19 19 18 16 12 16 20 19
     
  • 我们会发现,当k被填满后,每m+1个就是一个循环,那么m+1就是循环节
  • 然后两个19+1=20后,每个往后一个都是对应的2+18=20,4+16=20,8+12=20...
  • 最后我们就可以处理出前面的,然后得到后面的就行了

代码

 1 #include <cstdio>
 2 #include <iostream>
 3 #define ll long long 
 4 #define N 10010
 5 using namespace std;
 6 ll n,m,k,w,f[N],g[N];
 7 int main()
 8 {
 9     scanf("%lld%lld%lld",&n,&m,&k),f[0]=g[0]=1;
10     if (m==1) { printf("0"); return 0;}
11     for (int i=1;i<=n;i++)
12     {
13         f[i]=min(k-g[i-1],g[i-1]-((i>=m)?f[i-m]:0)),g[i]=g[i-1]+f[i]-((i>=m)?f[i-m]:0);
14         if (f[i]+g[i-1]==k) { w=i; break; }
15     }
16     if (w==n||!w) printf("%lld",g[n]);
17     else 
18     {
19         if ((n%=m+1)<=w) n+=m+1; 
20         if (n-m>=0) printf("%lld",k-f[n-m]); else printf("%lld",k);
21     }
22 }

 

posted @ 2019-01-27 20:38  BEYang_Z  阅读(288)  评论(0编辑  收藏  举报