The 2018 ACM-ICPC上海大都会赛 J Beautiful Numbers (数位DP)
生活随笔
收集整理的這篇文章主要介紹了
The 2018 ACM-ICPC上海大都会赛 J Beautiful Numbers (数位DP)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
題意:求小于等于N且能被自己所有位上數之和整除的數的個數。
分析:裸的數位dp。用一個三位數組dp[i][j][k]記錄:第i位,之前數位之和為j,對某個mod余數為k的狀態下滿足條件的個數。這里mod的值就是小于等于N的數中,所有可能出現的數位之和。所以solve函數中需要對dfs函數做一個循環,上限是9*pos(數位之和不會超過9*pos)。
還有需要注意的是,在遞歸的時候可以通過判斷當前數位之和sum是否超過mod,超過的話肯定在這個狀態下沒有滿足條件的數,以此剪枝優化。
#include<bits/stdc++.h> using namespace std; const int maxn=3e5+5; const int INF =0x3f3f3f3f; typedef long long LL; int a[20]; LL dp[13][105][150]; //dp[i][j][k]記錄 第i位,前面數位之和為j,對某個mod的余數是k的狀態下滿足條件的個數 int mod;LL dfs(int pos,int sum,int remain,bool limit){if(pos==-1) return (sum==mod && !remain);if(dp[pos][sum][remain]!=-1 && !limit) return dp[pos][sum][remain];int up = limit? a[pos]:9;LL res=0;for(int i=0;i<=up;++i){if(i+sum>mod) break; //剪枝res+=dfs(pos-1,sum+i,(remain*10+i)%mod,limit && i==a[pos]);}if(!limit) dp[pos][sum][remain] = res;return res; }LL solve(LL N) {int pos=0;LL x=N;while(x){a[pos++]=x%10;x/=10;}LL res=0;for(int i=1;i<=9*pos;++i){mod=i; memset(dp,-1,sizeof(dp)); //這里的dp數組記錄的只是針對一種模數的狀態,所以每次都要清空res+=dfs(pos-1,0,0,true);}return res; }int main(){int T,M,num,t,x;LL N;#ifndef ONLINE_JUDGEfreopen("in.txt","r",stdin);freopen("out.txt","w",stdout);#endifwhile(scanf("%lld",&N)==1){printf("%lld\n",solve(N));}return 0; }?
轉載于:https://www.cnblogs.com/xiuwenli/p/9383809.html
總結
以上是生活随笔為你收集整理的The 2018 ACM-ICPC上海大都会赛 J Beautiful Numbers (数位DP)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【深度学习】mask_rcnn训练自己的
- 下一篇: 算法笔记(胡凡)刷题笔记目录