• JZOJ 1981. 【2011集训队出题】Digit


    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
    ");
    }
    
    
  • 相关阅读:
    【案例】图片上传
    BOM相关知识点
    【案例】图片无缝轮播效果
    DOM相关知识点
    【案例】雪花飘落效果
    DOM节点克隆
    DOM节点的创建、插入、删除
    【案例】列表全选、全不选、反选
    AJAX相关概念及应用
    解决跨域问题
  • 原文地址:https://www.cnblogs.com/patricksu/p/8207036.html
Copyright © 2020-2023  润新知