題意:
一個整數如果按從低位到高位的順序,奇數位(個位、百位、萬位……)上的數字是奇數,偶數位(十位、千位、十萬位……)上的數字是偶數,我們就稱之為“好數”。
給定一個正整數?N,請計算從?1?到?N?一共有多少個好數。
思路:
這里不對暴力進行講解,網上有非常多的題解,做法也很簡單,這個做法的緣由是我沒看數據量,認錯了,以為是數位dp,當時沒做出來,現在補上,也算是學習數位dp了
參考題解:P10424 [藍橋杯 2024 省 B] 好數 數位dp_藍橋杯好數問題-CSDN博客
原題主里面的cnt--是不必要的,講錯了
思路其實也不難,就是標準的數位dp,這里講解是怎么來理解這道題的數位dp的
dp[i]表示的是,當前位置之前填寫最高位的這個時刻,填剩下所有可能數的大小,往后就是默認填寫最高位數字的,如果不是很明白推薦? 董曉老師的數位dp
1.dp[i]代表當前這一位在填寫[1,3,5,7,9]或者[0,2,4,6,8](注意要小于數本身)的可能算上所有的個數,因為高位固定,低位一定能兩個區間都能取的,直接預處理pre數組,進行計算就好。個數就是能填的個數xpre[i],注意不包括本身
2.為什么不包括本身,因為本身是不可直接計算的,因為你計算的話可能超過本身的數。dp那里計算的是一定能得到的所有數,所以最后有一個if,判斷最后dp結束的那個數本身。
3.但這并沒有結束,因為其實奇數位是能填0的,前提是高位沒有任何數,所以加上最后的個數,就是答案。
代碼:
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define endl '\n'
#define IOS ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
const int N = 2e5+10;
const int INF = 1e18;
const int MOD = 1e9+7;int pre[20],num[20];void solve(){int n;cin >> n;pre[1]=1;for(int i=2;i<20;i++){pre[i]=pre[i-1]*5;}int cntt=1;while(n){num[cntt++]=n%10;n/=10;}cntt--;int sum=0;for(int i=cntt;i>=0;i--){int cur=num[i];if(cur){int cnt=0;if(i&1){cnt+=cur/2;}else{cnt+=(cur+1)/2;}sum+=cnt*pre[i];}if( (i&1) != (num[i]&1) ){break;}if(i==1 && num[i]&1){sum++;}}for(int i=cntt;i>1;i--){if(i&1){sum+=pre[i];}}cout << sum << endl;}signed main() {IOS;int t = 1;
// cin >> t;while (t--) {solve();}}
?