Java教程

被3整除的子序列

本文主要是介绍被3整除的子序列,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

原题:https://ac.nowcoder.com/acm/problem/21302

给你一个长度为50的数字串,问你有多少个子序列构成的数字可以被3整除
答案对1e9+7取模

根据题目意思,我们直接考虑使用dp。
但是这个状态转移方程是真的不好想啊!

我们都知道可以被3整除的数,其各位数和能被3整除,那么我们只需要记录前i位,各位数和%3的情况,最后输出dp[length][0]即为答案。

#include<iostream>
#include<queue>
#include<stack>
using namespace std;
const int m = 1e9 + 7;
int dp[55][3];
int main()
{
	string a;
	cin >> a;
	int l = a.length();
	int rest = (a[0]-'0') % 3;
	dp[0][rest] = 1;
	for (int i = 1; i < l; i++)
	{
		int rest = (a[i]-'0') % 3;
		dp[i][rest]++;
		for (int j = 0; j < 3; j++)
		{
			dp[i][j] += (dp[i - 1][j] + dp[i - 1][(j + 3 - rest) % 3]) % m;//若求得rest为1,那么当前这个rest,与前i-1位余数为1的情况,可以组成2,与前面余数为0的情况又可以组成1.
		}
	}
	cout << dp[l - 1][0] << endl;
}

dp[i][j] += (dp[i - 1][j] + dp[i - 1][(j + 3 - rest) % 3]) % m;
很容易理解的是,dp[i][j]得加上前i-1位余数为j的情况。
第二个就是要加上合成的情况。
比如说第i位的余数为2,那么我们加上前面i-1位余数为1情况,就可以合成余数为0的情况。
这个就是j+3-rest的含义。

这篇关于被3整除的子序列的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!