[HDU 2065][dp]"红色病毒"问题

本文介绍了一种使用动态规划解决“红色病毒”问题的方法,该问题是关于计算满足特定条件的字符串数量。通过将状态分为四类并利用递推公式进行计算,有效解决了问题,并考虑了结果的周期性。

“红色病毒”问题

Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 7414 Accepted Submission(s): 3064

Problem Description

医学界发现的新病毒因其蔓延速度和Internet上传播的”红色病毒”不相上下,被称为”红色病毒”,经研究发现,该病毒及其变种的DNA的一条单链中,胞嘧啶,腺嘧啶均是成对出现的。
现在有一长度为N的字符串,满足一下条件:
(1) 字符串仅由A,B,C,D四个字母组成;
(2) A出现偶数次(也可以不出现);
(3) C出现偶数次(也可以不出现);
计算满足条件的字符串个数.
当N=2时,所有满足条件的字符串有如下6个:BB,BD,DB,DD,AA,CC.
由于这个数据肯能非常庞大,你只要给出最后两位数字即可.

Input

每组输入的第一行是一个整数T,表示测试实例的个数,下面是T行数据,每行一个整数N(1<=N<2^64),当T=0时结束.

Output

对于每个测试实例,输出字符串个数的最后两位,每组输出后跟一个空行.

Sample Input

4
1
4
20
11
3
14
24
6
0

Sample Output

Case 1: 2
Case 2: 72
Case 3: 32
Case 4: 0

Case 1: 56
Case 2: 72
Case 3: 56

Author
Rabbit

Source
RPG专场练习赛

Recommend
lcy | We have carefully selected several similar problems for you: 2062 2069 2070 2073 2077

题解

这道题给我第一感觉就是dp,写题卡的过程中在网上找题解,没发现用dp写的。这里就贴一份吧。
首先我们把状态分一下:
一、A和C均为偶数,这就是要求的。
二、A为偶数、C为奇数。
三、A为偶数、C为奇数。
四、A为奇数、C为奇数。
下面直接用序号①②③④代替以上状态。
开一个dp数组,第一维记为串长,第二维则标记以上状态。
则①对应dp[i][0],②dp[i][1],③dp[i][2], ④dp[i][3]。
如dp[i][0]表示串长为i,A C数量均为偶数的数量。
初始状态dp[1][0] = 2, dp[1][1] = 1, dp[1][2] = 1, dp[1][3] = 0;
再推导递推式

串长为i的①串,可以由串长为i - 1的①串在后面添加 “B” 或 “D”, 或者串长为i - 1的②串+ “C”, 或串长为i - 1的③串 + “A”得到。

 dp[i][0] = dp[i - 1][0] * 2 + dp[i - 1][1] + dp[i - 1][2];

串长为i的②串可以由串长为i-1的①串+ “C”,或②串 + “B” 或 “D”, 或④串 + “A”得到。

 dp[i][1] = dp[i - 1][0]  + dp[i - 1][1] * 2 + dp[i - 1][3];

③串和②串相似

dp[i][2] = dp[i - 1][0]  + dp[i - 1][2] * 2 + dp[i - 1][3] ;

串长为i的④串可以由,串长为i - 1的②串 + “C” , ③串 + “A”,四串 + “B” 或 “D”。

dp[i][3] = dp[i - 1][1] + dp[i - 1][2] + dp[i - 1][3] * 2;

递推完成。不过本题还有一些小细节需要处理,题目要求的是末两位数字。如果直接在递推过程对100取模,会导致结果错误,我采取的做法是对推过程对10000取模,最后输出答案时再对100取模。
同时,由于n范围为2^64,直接递推到n肯定会超时。而最终答案只包含两位,所以其具有周期性是显而易见,打表出来,找下周期就可以解决了。

//#define LOCAL
#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <vector>
#include <map>
#include <set>
#include <stack>
#include <queue>
#include <iostream>
#include <cstdlib>
#include <algorithm>

using namespace std;

#define LL long long
#define ll long long
#define INF 0x3f3f3f3f
#define maxn MAX_N
#define MOD mod
#define MMT(x,i) memset(x,i,sizeof(x))
#define REP(i, n) for(int i = 0; i < n; i++)
#define FOR(i, n) for(int i = 1; i <= n; i++)
#define pb push_back
#define mp make_pair
#define X first
#define Y second

const LL MOD = 1e9 + 7;
const double pi = acos(-1.0);
const double E = exp(1);
const double EPS = 1e-8;

const int MAX_N = 1000010;
int dp[10010][4];
int main()
{
  #ifdef LOCAL
    freopen("in.txt", "r", stdin);
    freopen("out.txt", "w", stdout);
  #endif
  ios::sync_with_stdio(false);
  dp[0][0] = dp[0][1] = dp[0][2] = 1;
  dp[1][0] = 2, dp[1][1] = dp[1][2] = 1, dp[1][3] = 0;
  for(int i = 2; i <= 130; i++)
  {
    dp[i][0] = (dp[i - 1][0] * 2 + dp[i - 1][1] + dp[i - 1][2]) % 10000;
    dp[i][1] = (dp[i - 1][0]  + dp[i - 1][1] * 2 + dp[i - 1][3]) % 10000;
    dp[i][2] = (dp[i - 1][0]  + dp[i - 1][2] * 2 + dp[i - 1][3]) % 10000;
    dp[i][3] = (dp[i - 1][1] + dp[i - 1][2] + dp[i - 1][3] * 2) % 10000;
//    cout << i << " " << dp[i][0] % 100 << endl;
  }
  int T;
  while(cin >> T)
  {
    if(T == 0)  break;
    for(int cas = 1; cas <= T; cas++)
    {
      long long n;
      cin >> n;
      int ans = 0;
      if(n <= 11) ans = dp[n][0];
      else  ans = dp[(n - 11) % (ll)20 + 11][0];
      cout << "Case " << cas <<": " << ans % 100<< endl;
    }
    cout << endl;
  }
  return 0;
}
内容概要:本文档详细介绍了基于直驱永磁同步发电机(PMSG)的1.5MW风力发电系统在Simulink环境下的建模与仿真全过程,涵盖了风力机空气动力学模型、PMSG电磁特性建模、不可控整流与逆变电路、直流环节、空间矢量脉宽调制(SVPWM)技术以及核心控制策略的设计。重点实现了最大功率点跟踪(MPPT)控制以提升风能捕获效率,并构建了电压外环与电流内环协同工作的双闭环控制系统,通过仿真验证了系统在不同风速条件下稳定运行的能力及动态响应性能。; 适合人群:适用于具备电力系统、电机控制理论基础及Simulink仿真操作经验的研究生、科研人员和从事新能源发电系统开发的工程技术人员;特别适合正在进行风电系统建模、控制算法研究或完成相关毕业设计的专业人士。; 使用场景及目标:①深入理解直驱式PMSG风力发电系统的整体架构与工作机理;②掌握从物理部件建模到控制策略实现的完整Simulink仿真流程;③学习并复现MPPT控制、双闭环控制等关键技术方案;④为后续开展低电压穿越、并网稳定性分析、故障诊断等高级课题提供可靠的仿真平台支撑。; 阅读建议:建议结合Matlab/Simulink软件动手实践,逐模块搭建模型,重点关注各控制环节的参数设计与调试方法,同时可参照文中提供的其他风电相关资源进行拓展学习与对比分析。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值