ALGORITHM NOTE / ARCHIVE

Bingbong的奇偶世界

题目大意: 给定以字符串,问从中选出任意多个数字可以得到多少不含前导零偶数(可以重复)

题目链接在这里

题目大意: 给定以字符串,问从中选出任意多个数字可以得到多少不含前导零偶数(可以重复)

分析: 不会数学作法,用dp思维 dp[i][1] 表示[1...9]xxx 前ii个数字不含前导零的数字个数(至少两位起步,单独处理一位数) dp[i][2] 表示前i个数字不含前导零偶数的个数

if(当前位是0){ dp[i-1][1]会对dp[i][1]有贡献 dp[i-1][1]会对dp[i][2]有贡献:任意数字添上一个偶数就变成偶数了 }else{ dp[i][1]+1(相当于选第一个数,不能有前导零) dp[i-1][1]会对dp[i][1]有贡献 if(当前为是偶数){ dp[i-1][1]会对dp[i][2]有贡献:任意数字添上一个偶数就变成偶数 } }

特殊处理只有1为数的情况 最后答案为ans+dp[n][2]

#include<bits/stdc++.h>
using namespace std;
using i64 = long long;
#define ios ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);

const int mod = 1e9+7;
int n;
string s;
i64 ans;
i64 dp[200010][3];
//dp[i][0] [1..9]xxx
//dp[i][1] [1...9]xxxx[0,2,4,6,8]
signed main(){
    ios;
    cin>>n>>s;
    s = ' '+s;
    vector<int>a(n+1);
    for(int i = 1;i<=n;++i){
        a[i] = s[i]-'0';
        ans+=((s[i]-'0')%2==0);
    }
    for(int i = 1;i<=n;++i){
        dp[i][1] = dp[i-1][1];
        dp[i][2] = dp[i-1][2];
        if(a[i]==0){
            dp[i][1] = (dp[i][1]+dp[i-1][1])%mod;
            dp[i][2] = (dp[i][2]+dp[i-1][1])%mod;
        }else{
            dp[i][1] = (dp[i][1]+1LL)%mod;
            dp[i][1] = (dp[i][1]+dp[i-1][1])%mod;
            if(a[i]%2==0){
                dp[i][2] = (dp[i][2]+dp[i-1][1])%mod;
            }
        }
    }
    cout<<(ans+dp[n][2])%mod<<"\n";
    return 0;
}

蒟蒻好想会dp啊