非曰能,但好学。欢迎一起交流学习
问题分析
动态规划问题,定义好动态变量则成功了一半,找到变量的迭代关系怎成功一大半。
动态变量
变量定义,在adoptions的题解已经提及,引用如下
我们定义dp[i][j]为前i个中整除3余数为j(只有0,1,2三个数)的个数
我再啰嗦得解释一下,dp[i][0]是前i个数包好的所有能除3为0的集合的元素的个数, dp[i][1],dp[i][2]同理。我个人觉得在集合的概念下,考虑递推比较方便。
迭代关系
设给定的数列为,这里我对迭代关系说明一下。假设我们已经有了
,考虑新来了第i+1个数,怎么计算
.
考虑dp[i+1][j]对应的集合中的元素(子序列),其构成可以分为如下三类:
- 只包括前i个数,即dp[i][j]对应的集合中所有元素都是满足的
- 只包括第i+1个数,这时要考虑第i+1个数mod 3的余数是多少,若为j则可为这个dp[i+1][j]对应的集合加把劲儿,否则不行。
- 包括第i+1个数,也包括前i+1个数。可以通过选出dp[i][k]对应集合的每一个元素,在后面添加第i+1个数,为看使得新构造的子序列mod 3 结果为j, k应该满足(k+A[i+1])%3应该为j.
代码实现
最后附上本人拙劣的代码,仅供参考。
#include <bits/stdc++.h>
using namespace std;
class Solution
{
public:
vector<int> A;
vector<long long> dp;
void read()
{
string s;
getline(cin,s);
A = vector<int>(s.size());
//cout<<s<<endl;
for(int i=0; i<s.size(); i++)
A[i]=s[i]-'0';
}
void process()
{
dp = vector<long long>(3);
read();
for(int i=0; i<A.size(); i++)
{
long long atmp[3];
for(int ind=0; ind<3; ind++)
atmp[ind] = (dp[ind] + dp[(ind-A[i]%3+3)%3])%1000000007;
for(int ind=0; ind<3; ind++)
dp[ind] = atmp[ind];
dp[A[i]%3]++;
}
cout<<dp[0]<<endl;
}
};
int main()
{
Solution s;
s.process();
return 0;
}


京公网安备 11010502036488号