2017中國大學生程序設計競賽 - 網絡選拔賽 HDU 6156 數位DP
阿新 • • 發佈:2017-08-19
esp emp rt+ clas name 暴力 eof typedef n-1
題目鏈接:http://acm.hdu.edu.cn/showproblem.php?pid=6156
題意:如題。
解法:數位DP,暴力枚舉進制之後,就轉化成了求L,R區間的回文數的個數,這個直接做一個數位DP就好了。dp[jz][start][cur][state]表示jz進制下以start位起始到cur位狀態為state(1表示已經回文,0表示沒有回文)時回文數的個數。
#include <bits/stdc++.h> using namespace std; typedef long long LL; LL dp[40][40][40][2]; LL temp[100], num[100]; //dp[start][cur][state]表示以start位起始到cur位狀態為state(1表示已經回文,0表示沒有回文)時回文數的個數 LL dfs(int jz, int start, int cur, bool state, bool jud){ if(cur<0) return state; if(!jud&&dp[jz][start][cur][state]!=-1) return dp[jz][start][cur][state]; int mx = jud?num[cur]:jz-1; LL ret=0; for(int i=0; i<=mx; i++){ temp[cur]=i;//枚舉該位的值 if(start==cur&&i==0)//前導0 ret += dfs(jz,start-1,cur-1,state,jud&&i==mx); else if(state&&cur<(start+1)/2)//已經構成回文串 ret+=dfs(jz,start,cur-1,temp[start-cur]==i,jud&&i==mx); else//尚未構成回文串 ret+=dfs(jz,start,cur-1,state,jud&&i==mx); } if(!jud) dp[jz][start][cur][state]=ret; return ret; } LL f(LL n, LL jz){ int len = 0; while(n){ num[len++]=n%jz; n/=jz; } num[len]=0; return dfs(jz,len-1,len-1,1,1); } LL L,R,l,r; int main() { int T,ks=0; scanf("%d", &T); memset(dp,-1,sizeof(dp)); while(T--) { LL ans = 0; scanf("%lld%lld%lld%lld",&L,&R,&l,&r); for(LL i=l; i<=r; i++){ if(L>R) swap(L,R); LL ret = f(R,i)-f(L-1,i); ans += ret*i+(R-L+1-ret); } printf("Case #%d: %lld\n", ++ks, ans); } return 0; }
2017中國大學生程序設計競賽 - 網絡選拔賽 HDU 6156 數位DP