1. 程式人生 > >JZOJ 1981. 【2011集訓隊出題】Digit

JZOJ 1981. 【2011集訓隊出題】Digit

string ble 沒有 body inline line while time %d

JZOJ 1981. 【2011集訓隊出題】Digit

Time Limits: 1000 ms Memory Limits: 128000 KB

Description  

在數學課上,小T又被老師發現上課睡覺了。為了向全班同學證明小T剛才沒有好好聽課,數學老師決定出一道題目刁難一下小T,如果小T答不出,那麽……

  情節就按照俗套的路線發展下去了,小T顯然無法解決這麽復雜的問題,可憐的小T只能向你求助:
  題目是這樣的:
  求一個滿足條件的n位數A(不能有前導0),滿足它的數字和為s1,並且,A*d的數字和為s2.

Input

一行四個整數:n, s1, s2, d

Output  

若存在最小的滿足條件的數,則輸出這個數,否則輸出-1。

Sample Input

2 9 9 5

Sample Output

18

Data Constraint

Hint

【樣例說明】
  1+8=9
  185=90
  9+0=9
【數據範圍】
  對於20%的數據滿足n≤5。
  對於50%的數據滿足n≤40
  對於100%的數據滿足1≤n≤100,0≤s1≤n
9,0≤s2≤(n+1)*9,0≤d≤9

Solution

很容易就想到一個4維的狀態: \(f[i,j,k,p]\)表示做到第i位,原數位和為j,乘d之後的數位和為k,並且乘d之後向前進位為p,是從哪一個轉移過來的,顯然f數組記錄的數據不足。

所以,就將一維i放進f裏面。所以狀態就變成了3維。(i不足的可以用0補齊所以只用保留長度最短的)

先枚舉答案的第一位是什麽,還要再枚舉p進位是多少。
這個答案的長度可能不一定為n,然後補0(不影響進位),越靠前越優。

Code

#include<cstdio>
#include<cstring>
#include<cmath>
#include<queue>
#include<algorithm>
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define fd(i,a,b) for(int i=a;i>=b;i--)
#define rep(i,x) for(int i=head[x];i;i=e[i].next)
#define mem(a,x) memset(a,x,sizeof(a)) #define mec(a,x) memcpy(a,x,sizeof(a)) typedef long long LL; typedef double DB; using namespace std; template <typename T> inline T read(T &a) { T x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9') f=(ch=='-')?-1:f,ch=getchar(); while(ch>='0'&&ch<='9') x=x*10+(ch-'0'),ch=getchar();a=f*x; } using namespace std; const int N=1000,inf=0x3f3f3f3f; int n,s1,s2,d,_x,_y,_z; int f[N][N][10],g[N][N][10],W[N],Q[N]; int x,y,z,ans,now,pos; bool cmp(int x1,int y1,int z1,int x2,int y2,int z2) { if((x1||x2||y1||y2||z1||z2)==0) return 0; if(g[x1][y1][z1]/10<g[x2][y2][z2]/10) return 1; if(g[x1][y1][z1]/10>g[x2][y2][z2]/10) return 0; now=g[x1][y1][z1]/10,z1=g[x1][y1][z1]%10,x1=x1-now,y1=y1-(now*d+z1)%10; now=g[x2][y2][z2]/10,z2=g[x2][y2][z2]%10,x2=x2-now,y2=y2-(now*d+z2)%10; return cmp(x1,y1,z1,x2,y2,z2); } bool cmp1(int* a,int* b) { fo(i,0,max(a[0],b[0])) { if(a[i]<b[i]) return 1; if(a[i]>b[i]) return 0; } return 0; } void getans(int x,int y,int z,int last,int* ans) { int len=n-f[x][y][z]-1; mem(ans,0),ans[ans[0]=1]=last; while(x||y||z) { if(g[x][y][z]/10*d/10+last*d%10<10) while(len)len--,ans[++ans[0]]=0; ans[++ans[0]]=g[x][y][z]/10; last=g[x][y][z]/10; now=g[x][y][z]/10,z=g[x][y][z]%10,x=x-now,y=y-(now*d+z)%10; } while(len)len--,ans[++ans[0]]=0; } int main() { freopen("1.in","r",stdin); read(n),read(s1),read(s2),read(d); mem(f,inf),mem(W,inf),ans=inf; f[0][0][0]=0; fo(i,0,s1) fo(j,0,s2) fo(k,0,9) if(f[i][j][k]<=n) { fo(now,0,9) { int x=i+now,y=j+(now*d+k)%10,z=(now*d+k)/10; if(f[i][j][k]+1<f[x][y][z]) f[x][y][z]=f[i][j][k]+1,g[x][y][z]=now*10+k; else if(f[i][j][k]+1==f[x][y][z]) { if(now<g[x][y][z]/10) g[x][y][z]=now*10+k; else if(now==g[x][y][z]/10) { _z=g[x][y][z]%10,_x=x-g[x][y][z]/10,_y=y-((g[x][y][z]/10)*d+_z)%10; if(cmp(i,j,k,_x,_y,_z)) g[x][y][z]=now*10+k; } } } } fo(h,1,9) { x=s1-h,now=ans=inf; if(x<0) continue; fo(tz,0,9) { z=tz,y=s2-(h*d+z)%10-(h*d+z)/10; if(y<0) continue; if(f[x][y][z]<n) { getans(x,y,z,h,Q); if(cmp1(Q,W)) ans=0,pos=tz,mec(W,Q); } } if(ans<n) {fo(i,1,n) printf("%d",W[i]);break;} } if(ans>=n) printf("-1\n"); }

JZOJ 1981. 【2011集訓隊出題】Digit