BZOJ 1386. [Baltic2000]Stickers 题解

BZOJ 1386. [Baltic2000]Stickers 题解

首先一个一个位置考虑,假设是\(z\)不够用了。

数位dp。

\(dp[i][j][0/1]\)表示\([0,10^i]\)内如果\(a_z=j\),前面的位是否存在非0数,的最小前缀(总共-用掉)

\(sum[i][j][0/1]\)表示考虑\([0,10^i]\)内如果\(a_z=j\)最后会剩下多少\(z\)

需要高精度。

code:

#include<bits/stdc++.h>
#define rb(a,b,c) for(int a=b;a<=c;++a)
#define rl(a,b,c) for(int a=b;a>=c;--a)
#define LL long long
#define IT iterator
#define PB push_back
#define II(a,b) make_pair(a,b)
#define FIR first
#define SEC second
#define FREO freopen("check.out","w",stdout)
#define rep(a,b) for(int a=0;a<b;++a)
#define SRAND mt19937 rng(chrono::steady_clock::now().time_since_epoch().count())
#define random(a) rng()%a
#define ALL(a) a.begin(),a.end()
#define POB pop_back
#define ff fflush(stdout)
#define fastio ios::sync_with_stdio(false)
#define check_min(a,b) a=min(a,b)
#define check_max(a,b) a=max(a,b)
using namespace std;
//inline int read(){
//    int x=0;
//    char ch=getchar();
//    while(ch<'0'||ch>'9'){
//        ch=getchar();
//    }
//    while(ch>='0'&&ch<='9'){
//        x=(x<<1)+(x<<3)+(ch^48);
//        ch=getchar();
//    }
//    return x;
//}
const int INF=0x3f3f3f3f;
typedef pair<int,int> mp;
/*}
*/
vector<int> operator + (vector<int> A,vector<int> B){
	reverse(ALL(A));
	reverse(ALL(B));
	if(A.size()<B.size()) swap(A,B);
	A.PB(0);
	rep(i,A.size()){
		if(i<B.size()) A[i]+=B[i];
		if(A[i]>=10){
			A[i+1]++;
			A[i]-=10;
		}
	}
	if(A.back()==0) A.POB();
	reverse(ALL(A));
	return A;
}
pair<vector<int>,vector<int> > operator + (pair<vector<int> ,vector<int> > A,pair<vector<int>,vector<int> > B){
	return II(A.FIR+B.FIR,A.SEC+B.SEC);
}
vector<int> bigint(int num){
	vector<int> ans;
	while(num){
		ans.PB(num%10);
		num/=10; 
	}
	reverse(ALL(ans));
	return ans;
}
bool comp(vector<int> A,vector<int> B){
	// A<B
	if(A.size()!=B.size()) return A.size()<B.size();
	return A<B;
}
bool comp(pair<vector<int>,vector<int> > A,pair<vector<int>,vector<int> > B){
	return comp(A.FIR+B.SEC,B.FIR+A.SEC);
}
pair<vector<int>,vector<int> > dp[90+1][90+10+1][2];
pair<vector<int>,vector<int> > sum[90+1][90+10+1][2];
int a[10];
vector<int> Ans;
vector<int> Best;
int Z;
void solve(int D,int J,bool flag,pair<vector<int>,vector<int> > sma){
	if(D==1){
		pair<vector<int>,vector<int> > Nowsum;
		rep(d,10){
			if(d==0&&!flag);
			else{
				if(J<90){
					Nowsum.SEC=Nowsum.SEC+bigint(90-J);
				}	
				else{
					Nowsum.FIR=Nowsum.FIR+bigint(J-90);
				}
			}
			if(d==Z){
				Nowsum.SEC=Nowsum.SEC+bigint(1);
			}
			if(comp(Nowsum,sma)){
				Ans.PB(d);
				break;
			}
		}
		return ;	
	} 
	pair<vector<int>,vector<int> > Tmp;
	rep(d,10){
		if(comp(Tmp+dp[D-1][J-((flag||d)&&d==Z)][flag|(d!=0)],sma)){
			Ans.PB(d);
			solve(D-1,J-((flag||d)&&d==Z),flag|(d!=0),II(sma.FIR+Tmp.SEC,sma.SEC+Tmp.FIR));
			return ;
		}
		Tmp=Tmp+sum[D-1][J-((flag||d)&&d==Z)][flag|(d!=0)];
	}
}
void print(vector<int> V){
	if(V.empty()){
		puts("0");
		return ;
	}
	for(auto it:V){
		cout<<it;
	}
	cout<<endl;
}
int main(){
	rep(i,10) scanf("%d",&a[i]);
	int Pre=INF;
	rb(Z_,1,10){
		int z=Z_%10;
		Z=z;
		if(a[z]>=Pre) continue;
		Pre=a[z];
		rb(j,1,90+10) rep(flag,2) {
			sum[1][j][flag].FIR.clear();
			sum[1][j][flag].SEC.clear();
			int f=10;
			if(!flag){
				f=9;
			}
			if(j>=90)
			sum[1][j][flag].first=bigint(f*(j-90));
			else
			sum[1][j][flag].SEC=bigint(f*(90-j));
			if(z!=0||flag){
				sum[1][j][flag].SEC=sum[1][j][flag].SEC+bigint(1);
			}
			dp[1][j][flag].FIR.clear();
			dp[1][j][flag].SEC.clear();
			if(!comp(sum[1][j][flag].SEC,sum[1][j][flag].FIR)) dp[1][j][flag]=sum[1][j][flag];
		}
		rb(i,2,89){
			rb(j,i,90+10){
				rep(flag,2){
					dp[i][j][flag].FIR.clear();
					dp[i][j][flag].SEC.clear();
					sum[i][j][flag].SEC.clear();
					sum[i][j][flag].FIR.clear();
					rep(d,10){
						pair<vector<int>,vector<int> > Tmp=II(sum[i][j][flag].FIR+dp[i-1][j-((flag||d)&&d==z)][flag|(d!=0)].FIR,sum[i][j][flag].SEC+dp[i-1][j-((flag||d)&&d==z)][flag|(d!=0)].SEC);
						if(!comp(dp[i][j][flag].FIR+Tmp.SEC,Tmp.FIR+dp[i][j][flag].SEC)){
							dp[i][j][flag]=Tmp;
						}
						sum[i][j][flag]=sum[i][j][flag]+sum[i-1][j-((flag||d)&&d==z)][flag|(d!=0)];
					}
				}
			}
		}
		Ans.clear();
		solve(89,90+a[z],0,II(bigint(0),bigint(0)));
		reverse(ALL(Ans));
		while(Ans.size()&&Ans.back()==0) Ans.POB();
		reverse(ALL(Ans));
		if(z==1||comp(Ans,Best)){
			Best=Ans;
		}
	}
	reverse(ALL(Best));
	Best[0]--;
	rep(i,Best.size()){
		if(Best[i]<0){
			Best[i]+=10;
			Best[i+1]--;
		}
	}
	if(Best.back()==0){
		Best.POB();
	}
	reverse(ALL(Best));
	for(auto it:Best){
		printf("%d",it);
	}
	return 0;
}

posted @ 2021-05-27 14:41  WWW~~~  阅读(72)  评论(0编辑  收藏  举报