質問の主な
アイデアへの質問リンク。
長さ50の数字の文字列を入力し、3で割り切れる数を構成するサブシーケンスの数を尋ねます。
答えは1 e 9 + 7 1e ^ 9 +7です。1 e9+7モジュロ
入力の説明
数字で構成される文字列を入力します。長さは50以下です。
出力の説明
整数入力の例を出力し
ます。
132
サンプル出力
3
動的プログラミング線形dp1
。状態f [i] [j] f [i] [j]を決定しますf[i][j]:以 s [ i ] s[i] s [ i ]の終わりの残りはjjですj、属性はスキームの数を表します。
2.状態遷移f [i + 1] [j] = f [i + 1] [j] + f [i] [j] f [i + 1] [j] = f [i + 1] [j] + f [i] [j]f [ i+1 ] [ j ]=f [ i+1 ] [ j ]+f [ i ] [ j ]
キビを例として、サンプルを取り上げます。まず、132のサブシーケンスには1、3、13、2、12、32、132があります。ある数は特定の数で割り切れるという結論があり、すべての位置の数の合計はこの数で割り切れ、2で終わります。データは2、12、32、132です。12はf ["12"] [mod] = f ["12"] [(mod + "2")%mod] + f ["1"] [mod] f ["12"] [mod]と見なすことができます= f ["12"] [(mod + "2")\%mod] + f ["1"] [mod]f [ " 1 2 " ] [ m o d ]=f [ " 1 2 " ] [ (m o d+" 2 " )%m o d ]+F [ " 1 " ] [ M O D ]など。
3.コーディングの実装
1 dp[1][1] = 1;
03 dp[2][0] = 1;
002 dp[3][2] = 1;
1 ⇒ 12
13 ⇒ 132 ⇒ dp[3][(j+2)%3] = (dp[2][j] + dp[3][(j+2)%3])
2
3 ⇒ 32
for(int i = 1; i <= len; i++)
for(int j = 0; j < 3; j++)
for(int k = i+1; k <= len; k++)
f[k][(s[k]+j-'0')%3] =(f[k][(s[k]+j-'0')%3]+ f[i][j])%mod;
#include <cstdio>
#include <cstring>;
using namespace std;
const int mod = 1e9 + 7;
char s[55];
int f[55][3];
int main()
{
scanf("%s",s+1);
int len = strlen(s+1);
for(int i = 1; i <= len; i++) f[i][(s[i]-'0')%3] = 1;
for(int i = 1; i <= len; i++)
for(int j = 0; j < 3; j++)
for(int k = i+1; k <= len; k++)
f[k][(s[k]+j-'0')%3] =(f[k][(s[k]+j-'0')%3]+ f[i][j])%mod;
int ans = 0;
for(int i = 1; i <= len; i++) ans = (ans + f[i][0])%mod;
printf("%d\n",ans);
return 0;
}