原题链接:登录—专业IT笔试面试备考平台_牛客网
解题思路:要说明的是,本题中子序列构造的数字,指的是子序列中值相加,而非直接组成一个多位数。
在明白这一点后,题目就变成了一个标准的动态规划。任何一个数被3余后都只会剩下三种结果——0,1,2。
首先,对于每一个数,不管前面的情况,其自身余3后的值所对应的情况必然会产生,因为存在前面都不选的情况。接下来是继承前面的情况,如果不选该数,那么这一层的0,1,2三种情况直接累加上上一层的结果就行。而如果选择,那么将该数加上上一层三种情况,再余3,就能找到在本层所对应的位置,加上位置上原有的数即可。
最后,输出最后一层的,余数为0的情况。
AC代码:
#include<bits/stdc++.h>
using namespace std;
#define MOD 1000000007
string m;
long long dp[60][3],i;//i用以在循环中顺带记录字符串有多长
int main(){
cin>>m;
for(i=1;m[i-1];i++){
int buffer;
buffer=(m[i-1]-'0')%3;
dp[i][buffer]=1;//直接获得该余数的情况,模拟了前面都不选
for(int j=0;j<3;j++){
dp[i][j]+=dp[i-1][j];//本数不选
dp[i][(j+buffer)%3]+=dp[i-1][j];//本数选
}
for(int j=0;j<3;j++) dp[i][j]%=MOD;
}
cout<<dp[i-1][0];
return 0;
}