小米oj 找小"3"(數位dp)
阿新 • • 發佈:2018-12-20
找小“3”
序號:#40難度:困難時間限制:1000ms記憶體限制:10M
描述
給定一個奇數n,可得到一個由從1到n的所有奇數所組成的數列,求這一數列中數字3所出現的總次數。例如當n=3時,可得到奇數列:1,3,其中有一個數字3,故可得1
輸入
一個奇數。表示n,0<n<9999999999。
輸出
一個整數,表示從 1 到 n 的奇數列中,數字 3 出現的次數。
輸入樣例
1 3 35
複製樣例
輸出樣例
0 1 7
#include<iostream> #include<string.h> #include<stdio.h> #include<algorithm> using namespace std; typedef long long ll; int bit[15]; ll n; ll ans; ll dp[15]; ll mypow(ll a,ll b) { if(b==0)return 2; ll ret=1; while(b--)ret*=a; return ret; } ll get(ll p) { if(p==0)return 1; ll tmp=1;ll res=0; for(ll i=1;i<=p;i++) { res+=bit[i]*tmp; tmp*=10; } return res; } ll dfs(ll pos,bool flag) { if(flag&&dp[pos]!=-1)return dp[pos]; if(pos==0)return 0; ll x=flag?9:bit[pos]; ll res=0; for(ll i=0;i<=x;i++) { if(i==3){ if(flag||i<x){res+=mypow(10,pos-1)/2;} else { res+=(get(pos-1)+1)/2; } res+=dfs(pos-1,flag||i<x); } else { res+=dfs(pos-1,flag||i<x); } } if(flag)dp[pos]=res; return res; } int main() { //freopen("in.txt","r",stdin); while(~scanf("%lld",&n)) { memset(dp,-1,sizeof(dp)); int cnt=0; while(n) { bit[++cnt]=n%10; n/=10; } ans=dfs(cnt,0); printf("%lld\n",ans); } return 0; }