非曰能,但好学。欢迎一起交流学习
问题分析
动态规划问题,定义好动态变量则成功了一半,找到变量的迭代关系怎成功一大半。
动态变量
变量定义,在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; }