1. 程式人生 > 實用技巧 >HDU6831 Fragrant numbers(區間dp)

HDU6831 Fragrant numbers(區間dp)

這題直覺上來說可以使用區間dp進行合法狀態的轉移,然後記錄最小值。

現在的問題是這個是個無限長度的串,因此我們可以大膽猜測,只需要其中一部分就能把所有的情況構造出來

經過打表處理後發現,只需要前13個以內就能構造出所有合法狀態,因此只需要這樣區間dp即可

#include<bits/stdc++.h>
#define getsz(p) (p?p->sz:0)
using namespace std;
typedef long long ll;
const int mod=1e9+7;
const int N=3e5+10;
int f[14][14][5050];
string s="
01145141919114514"; int st[N]; int ans[N]; int main(){ ios::sync_with_stdio(false); int t; cin>>t; memset(f,0,sizeof f); int len,i,j,k; int tmp=0; for(i=1;i<13;i++){ tmp=0; for(j=i;j<=(min(12,i+3));j++){ tmp=tmp*10
+(s[j]-'0'); if(tmp<=5000) f[i][j][tmp]=1; } } for(len=2;len<13;len++){ for(i=1;i+len-1<13;i++){ int j=i+len-1; for(k=i;k<j;k++){ for(int l=1;l<=5000;l++){
if(!f[i][k][l]) continue; for(int r=1;r<=5000;r++){ if(!f[k+1][j][r]) continue; if(l*r<=5000) f[i][j][r*l]=1; if(l+r<=5000) f[i][j][l+r]=1; } } } } } for(i=1;i<=13;i++){ for(j=1;j<=5000;j++){ if(f[1][i][j]&&(!ans[j])){ ans[j]=i; } } } while(t--){ int n; cin>>n; cout<<(ans[n]?ans[n]:-1)<<endl; } return 0; }
View Code