被3整除的子序列
題目描述
給你一個長度為50的數字串,問你有多少個子序列構成的數字可以被3整除
答案對1e9+7取模
輸入描述:
輸入一個字符串,由數字構成,長度小於等於50
輸出描述:
輸出一個整數
示例1
輸入
132
輸出
3
示例2
輸入
9
輸出
1
題目鏈接:
這題仔細想想,可以這樣寫,每個數字串都可以從第一個最后一個去考慮,設初始子序列個數為len,每增加一個數,子序列就變為2*len+1;
設dp[0],dp[1],dp[2],表示除3得到的余數分別為0,1,2。每增加一個數就更新一遍數組。
余數為0:dp[0]=dp[0]+dp[0]+1;
dp[1]=dp[1]+dp[1];
dp[2]=dp[2]+dp[2];
余數為1:dp[0]=dp[0]+dp[2];
dp[1]=dp[1]+dp[0]+1;
dp[2]=dp[2]+dp[1];
余數為2:dp[0]=dp[0]+dp[1];
dp[1]=dp[1]+dp[2];
dp[2]=dp[2]+dp[0]+1;
這個規律自己找幾個數測一下就有了
AC代碼
1 #include <iostream> 2 #include <cstdio> 3 #include <fstream> 4 #include <algorithm> 5 #include <cmath> 6 #include <deque> 7 #include <vector> 8 #include <queue> 9 #include <string> 10 #include <cstring> 11 #include <map> 12 #include <stack> 13 #include <set> 14 using namespace std; 15 const int Mod=1e9+7; 16 char ch[1000]; 17 int dp[3]; 18 int f(char s)//字符串轉換整數 19 { 20 return s-'0'; 21 } 22 int main() 23 { 24 cin.getline(ch,1000); 25 memset(dp,0,sizeof(dp)); 26 27 int len=strlen(ch); 28 for(int i=0; i<len; i++)//開始從第一個數遍歷 29 { 30 /* 31 重點來了,這步不能省,必須要開新的數保存,暫時不能改變dp的大小 32 等s0,s1,s2全部更新完以后才能去換,不然會影響結果, 33 假設余數為2:dp[0]=dp[0]+dp[1]; 34 dp[1]=dp[1]+dp[2]; 35 dp[2]=dp[2]+dp[0]+1; 36 如果這樣這樣更新會有一個問題,dp[0]改變之后,dp[2]=dp[2]+dp[0]+1; 37 用的就是新的dp[0],答案就不符合了 38 */ 39 int s0=0,s1=0,s2=0; 40 int x=f(ch[i]); 41 if(x%3==0) 42 { 43 s0+=dp[0]+1; 44 s1+=dp[1]; 45 s2+=dp[2]; 46 } 47 if(x%3==1) 48 { 49 s0+=dp[2]; 50 s1+=dp[0]+1; 51 s2+=dp[1]; 52 } 53 if(x%3==2) 54 { 55 s0+=dp[1]; 56 s1+=dp[2]; 57 s2+=dp[0]+1; 58 } 59 //統一更新 60 dp[0]+=s0; 61 dp[1]+=s1; 62 dp[2]+=s2; 63 for(int j=0; j<3; j++)//每次對1e9+7取余; 64 dp[j]=dp[j]%Mod; 65 } 66 cout << dp[0] << endl; 67 }
