• Nowcodercontest5278H 纸牌游戏


    Nowcodercontest5278H 纸牌游戏

    可以合理地想到从高到低依次枚举每一位的数,然后\(\text{Check}\)一下后面是否存在方案,问题在于如何快速Check

    设还还剩下的\(\mod 3=0,1,2\)的数个数分别为\(c[0..2]\)

    设总共还需要\(n\)个,需要凑出\(\mod 3=t\)的方案

    这时后我们假设枚举某一个,比如我们枚举\(0\)选了\(i\)个,设还剩下\(n-i\)个要选,设剩下两个选了\(y,x\)个,则有限制条件

    \[x+y=n-i \]

    \[2x+y = t \ (\mod 3) \]

    \(x\)带掉,得到

    \[2n-2i-2y+y=t (\mod 3) \]

    \[y=2n-2i-t (\mod 3) \]

    我们可以根据各种限制条件解出\(y\)的可行区间,然后判断区间内是否存在一个\(y\)即可

    同时我们可以发现,随\(i\)的增大,\(y\)的可行范围也会增大,所以可以直接枚举最大的3个\(i\)就能完成check

    #include<cstdio>
    #include<cctype>
    #include<queue>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #include<set>
    #include<cmath>
    using namespace std;
    
    #define reg register
    typedef long long ll;
    #define rep(i,a,b) for(reg int i=a,i##end=b;i<=i##end;++i)
    #define drep(i,a,b) for(reg int i=a,i##end=b;i>=i##end;--i)
    
    #define pb push_back
    template <class T> inline void cmin(T &a,T b){ ((a>b)&&(a=b)); }
    template <class T> inline void cmax(T &a,T b){ ((a<b)&&(a=b)); }
    
    char IO;
    template<class T=int> T rd(){
    	T s=0;
    	int f=0;
    	while(!isdigit(IO=getchar())) if(IO=='-') f=1;
    	do s=(s<<1)+(s<<3)+(IO^'0');
    	while(isdigit(IO=getchar()));
    	return f?-s:s;
    }
    
    const int N=1e5+10;
    
    int n,m;
    char s[N],ans[N];
    int cnt[10],c[3];
    
    int Check(int n,int t){
    	rep(i,0,2) c[i]=0;
    	rep(i,0,9) c[i%3]+=cnt[i];
    	// x+y=n-i
    	// x<=c[2] ,y<=c[1]
    	// 2x+y=t (mod 3)
    	// x=n-i-y
    	// 2n-2i-2y+y=t(mod 3)
    	// 2n-y-2i=t(mod 3)
    	// y=2n-2i-t (mod 3)
    	int l0=max(0,n-c[1]-c[2]),r0=min(n,c[0]);
    	drep(i,r0,max(l0,r0-4)) {
    		int y=2*n-2*i-t;
    		y=(y%3+3)%3;
    		int l=max(0,n-i-c[2]),r=min(c[1],n-i); // y=的可行范围
    		while(l%3!=y) l++;
    		if(l<=r) return 1;
    	}
    	return 0;
    }
    
    int main(){
    	rep(kase,1,rd()) {
    		scanf("%s",s+1),n=strlen(s+1),m=rd();
    		rep(i,0,9) cnt[i]=0;
    		rep(i,1,n) cnt[s[i]-'0']++;
    		int fl=1,c=0;
    		rep(i,1,m) {
    			ans[i]=0;
    			drep(j,9,0) if(cnt[j]) {
    				cnt[j]--;
    				int t=3-c-j;
    				t=(t%3+3)%3;
    				int fl=Check(m-i,t);
    				if(fl) {
    					ans[i]=j+'0';
    					c=(c+j)%3;
    					break;
    				}
    				cnt[j]++;
    			}
    			if(!ans[i] || (i==1 && m>1 && ans[i]=='0') ) {
    				fl=0;
    				break;
    			}
    		}
    		ans[m+1]=0;
    		puts(!fl?"-1":ans+1);
    	}
    }
    
    
    
  • 相关阅读:
    android studio 使用(一)
    【转】How to Change File Ownership & Groups in Linux
    ubuntu 14.04安装nodejs
    基于源码学习-fighting
    linux shell操作
    linux用户管理
    ubutu强制结束进程 kill -9 ProcessID
    ubuntu 添加和删除用户
    ubuntu 14.04查看java的安装路径
    vuex 中关于 mapState 的作用
  • 原文地址:https://www.cnblogs.com/chasedeath/p/12727079.html
Copyright © 2020-2023  润新知