• 【超好懂的比赛题解】HNCPC Multi-university Training Round3 比赛题解



    title : HNCPC Multi-university Training Round3
    date : 2022-7-29
    tags :ACM,练习记录
    author : LINNO


    HNCPC Multi-university Training Round3比赛题解

    没补的题有EIK。按难度顺序。

    A - Bank Transfer

    签到题,照题意算税收。

    //#pragma GCC optimize("Ofast", "inline", "-ffast-math")
    //#pragma GCC target("avx,sse2,sse3,sse4,mmx")
    #include
    #define inf 0x3f3f3f3f
    #define int long long
    using namespace std;
    const int N=2e5+7;
    const int mod=1e9+7;
    
    //int read(){	int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-') f=f*-1;ch=getchar();}while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}return x*f;}
    //void write(int x){if(x>9) write(x/10);putchar(x%10+'0');}
    double k,ans;
    
    void Solve(){
    	scanf("%lf",&k);
    	ans=25.0+0.01*k;
    	if(ans<100) ans=100.00;
    	else if(ans>2000) ans=2000.00;
    	printf("%.2lf",ans);
    }
    
    signed main(){
    	int T=1;
    	while(T--){
    		Solve();
    	}
    	return 0;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29

    F - SMS from MCHS

    签到题,照题意判断输出哪个语句。

    //#pragma GCC optimize("Ofast", "inline", "-ffast-math")
    //#pragma GCC target("avx,sse2,sse3,sse4,mmx")
    #include
    #define inf 0x3f3f3f3f
    #define int long long
    using namespace std;
    const int N=2e5+7;
    const int mod=1e9+7;
    
    //int read(){	int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-') f=f*-1;ch=getchar();}while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}return x*f;}
    //void write(int x){if(x>9) write(x/10);putchar(x%10+'0');}
    int t1,v1,t2,v2;
    
    void Solve(){
    	cin>>t1>>v1>>t2>>v2;
    	if(t2<0&&v2>=10) cout<<"A storm warning for tomorrow! Be careful and stay home if possible!\n";
    	else if(t2<t1) cout<<"MCHS warns! Low temperature is expected tomorrow.\n";
    	else if(v2>v1) cout<<"MCHS warns! Strong wind is expected tomorrow.\n";
    	else cout<<"No message\n"; 
    }
    
    signed main(){
    //	ios::sync_with_stdio(0);
    //	cin.tie(0);cout.tie(0);
    //  freopen("in.cpp","r",stdin);
    //  freopen("out.cpp","w",stdout);
    	int T=1;
    //	cin>>T;
    //	clock_t start,finish;
    //	start=clock();
    	while(T--){
    		Solve();
    	}
    //	finish=clock();
    //	cerr<<((double)finish-start)/CLOCKS_PER_SEC<
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37

    D - Multiple Subject Lessons

    队友过的题,给定最开始拥有的数字和每个数字能涂的颜色,数字可以整数划分,问总共能够产生多少种集合。(存在数字不同或者某一个数字颜色不同则集合不同)

    数据很小,爆搜+打表就能过。

    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #define int long long
    using namespace std;
    long long ans,f[10005],g[10005],s[10005],n,num,sum,col[10005],K;
    long long a[100][100]= {{0},{0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15},{0,1,3,6,10,15,21,28,36,45,55,66,78,91,105,120},{0,1,4,10,20,35,56,84,120,165,220,286,364,455,560,680},{0,1,5,15,35,70,126,210,330,495,715,1001,1365,1820,2380,3060},{0,1,6,21,56,126,252,462,792,1287,2002,3003,4368,6188,8568,11628},{0,1,7,28,84,210,462,924,1716,3003,5005,8008,12376,18564,27132,38760},{0,1,8,36,120,330,792,1716,3432,6435,11440,19448,31824,50388,77520,116280},{0,1,9,45,165,495,1287,3003,6435,12870,24310,43758,75582,125970,203490,319770},{0,1,10,55,220,715,2002,5005,11440,24310,48620,92378,167960,293930,497420,817190},{0,1,11,66,286,1001,3003,8008,19448,43758,92378,184756,352716,646646,1144066,1961256},{0,1,12,78,364,1365,4368,12376,31824,75582,167960,352716,705432,1352078,2496144,4457400},{0,1,13,91,455,1820,6188,18564,50388,125970,293930,646646,1352078,2704156,5200300,9657700},{0,1,14,105,560,2380,8568,27132,77520,203490,497420,1144066,2496144,5200300,10400600,20058300},{0,1,15,120,680,3060,11628,38760,116280,319770,817190,1961256,4457400,9657700,20058300,40116600},{0,1,16,136,816,3876,15504,54264,170544,490314,1307504,3268760,7726160,17383860,37442160,77558760}};
    int dfs(int k,int t,int m) {
    	if (k<1) {
    		if (t==0) {
    			//ans++;
    			long long sum=1;
    			for (int i=1; i<=num; ++i)
    				if (a[f[i]][K]) sum=sum*a[f[i]][K];
    			ans+=sum;
    		}
    		return 0;
    	}
    	for (int i=0; i<=m; ++i) {
    		if (t-i*k>=0) {
    			f[++num]=i;
    			g[num]=k;
    			dfs(k-1,t-i*k,m);
    			--num;
    		} else
    			break;
    	}
    	return 0;
    }
    int calu(int x,int all,int k) {
    	if (k>all) {
    		if (x==0)
    			sum++;
    		return 0;
    	}
    	for (int i=0; i<=15; ++i) {
    		if (x>=i) {
    			col[k]=i;
    			calu(x-i,all,k+1);
    			col[k]=0;
    		} else break;
    	}
    }
    signed main() {
    	cin>>n;
    	cin>>K;
    	dfs(n,n,n);
    	cout<<ans;
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53

    B - Bacteria

    给定n,构造长度为 2 n 2^n 2n的01串,使得从原串开始二分得到的子串种数最多(就是把一个串按中间分为左右个子串,然后子串再继续这样划分)。

    构造思路:0000~1111一共有16种不同的字符,每个长度为4,那么将0和15、1和14…7和8拼在一起是一个最优的方案,可以拼 2 7 2^7 27的长度,那我们确认一下n的范围按,然后照同样的方法把 2 20 2^{20} 220次方搞出来就可以了。n<=4的时候按人类智慧写一下。

    #include
    #define inf 0x3f3f3f3f
    #define int long long
    using namespace std;
    const int N=(1<<24);
    const int mod=1e9+7;
    
    int n,mp[N],vt[N],res=0,mx=0;
    char now[N];
    string ans;
    
    void Solve(){
    	cin>>n;
    	int len=(1<<n);
    	if(n==1){
    		ans="01";
    	}else if(n==2){
    		ans="0110";
    	}else if(n==3){
    		ans="00100111";
    	}else if(n==4){
    		ans="0110001111001001";
    	}else if(n<=7){
    		int idx=0,lf=0,rg=(1<<4)-1;
    		while(idx<len){
    			int tmpl=lf,tmpr=rg;
    			for(int j=0;j<4;++j) now[++idx]=tmpl%2+'0',tmpl/=2;
    			for(int j=0;j<4;++j) now[++idx]=tmpr%2+'0',tmpr/=2;
    			++lf;--rg;
    		}
    		printf("%s",now+1);
    		return;
    	}else if(n<=11){
    		int idx=0,lf=0,rg=(1<<8)-1;
    		while(idx<len){
    			int tmpl=lf,tmpr=rg;
    			for(int j=0;j<8;++j) now[++idx]=tmpl%2+'0',tmpl/=2;
    			for(int j=0;j<8;++j) now[++idx]=tmpr%2+'0',tmpr/=2;
    			++lf;--rg;
    		}
    		printf("%s",now+1);
    		return;
    	}else{
    		int idx=0,lf=0,rg=(1<<16)-1;
    		while(idx<len){
    			int tmpl=lf,tmpr=rg;
    			for(int j=0;j<16;++j) now[++idx]=tmpl%2+'0',tmpl/=2;
    			for(int j=0;j<16;++j) now[++idx]=tmpr%2+'0',tmpr/=2;
    			++lf;--rg;
    		}
    		printf("%s",now+1);
    		return;
    	}
    	cout<<ans<<"\n";
    }
    
    signed main(){
    	int T=1;
    	while(T--){
    		Solve();
    	}
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63

    J - Straight

    队友过的题,没看。

    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #define int long long
    using namespace std;
    const int N=200005;
    int n,m,s,cnt,num,a[N],b[N],c[N],d[N],ans,ansl[N],ansr[N];
    signed main() {
    	cin>>n>>m>>s;
    	int M=m;
    	for (int i=1; i<=m; ++i) {
    		scanf("%lld",&a[i]);
    	}
    	if (m>n) {
    		cout<<0;
    		return 0;
    	}
    	sort(a+1,a+1+m);
    	for (int i=1; i<=m; ++i) {
    		if (a[i]==a[i-1]) continue;
    		else b[++cnt]=a[i];
    	}
    	int need=m-s;
    	m=cnt;
    	if (cnt<need) {
    		cout<<0;
    		return 0;
    	}
    	for (int i=1; i<=m; ++i) {
    		if (i+need-1>m) break;
    		int less=s-(b[i+need-1]-b[i]-1-(need-2));
    		if (less>=0) {
    			++num;
    			c[num]=b[i]-less;
    			d[num]=min(b[i],n-M+1);
    			if (c[num]<=0) c[num]=1;
    		}
    	}
    	if (num==0) {
    		cout<<0;
    		return 0;
    	}
    	int l=c[1],r=d[1];
    	cnt=0;
    	for (int i=1; i<=num; ++i) {
    		if (c[i]<=d[i-1]) {
    			c[i]=d[i-1]+1;
    		}
    		if (d[i]>=c[i]) {
    			ans+=d[i]-c[i]+1;
    		}
    	}
    	cout<<ans;
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58

    C - Check Markers

    给n堆东西,其中每堆都有ai个坏的和bi个好的,每次你可以从两堆之中个取一个(你不能控制取到好的还是坏的),问最终是否不能从两堆之中都取到好的。

    我们肯定每次取都是一好一坏,那么推一推不等式可以知道最终不能取到两个好的条件为 有某一堆 ∑ b − b i < = ∑ a , 并且记其他堆坏的加起来比该堆好的多的堆数唯一 有某一堆\sum b-b_i <=\sum a ,\\并且记其他堆坏的加起来比该堆好的多的堆数唯一 有某一堆bbi<=a,并且记其他堆坏的加起来比该堆好的多的堆数唯一

    //#pragma GCC optimize("Ofast", "inline", "-ffast-math")
    //#pragma GCC target("avx,sse2,sse3,sse4,mmx")
    #include
    #define inf 0x3f3f3f3f
    #define int long long
    using namespace std;
    const int N=2e5+7;
    const int mod=1e9+7;
    
    //int read(){	int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-') f=f*-1;ch=getchar();}while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}return x*f;}
    //void write(int x){if(x>9) write(x/10);putchar(x%10+'0');}
    int n,a[N],b[N],c[N],vis[N];
    
    void Solve(){
    	cin>>n;
    	int suma=0,sumb=0,flag=0,fg=0;
    	for(int i=1;i<=n;++i){
    		cin>>a[i]; 	
    		suma+=a[i];
    	}
    	for(int i=1;i<=n;++i){
    		cin>>b[i];
    		sumb+=b[i];
    		c[i]=a[i]+b[i];
    		if(c[i]<=suma) ++flag,vis[i]=1;
    		else vis[i]=0;
    	}
    	for(int i=1;i<=n;++i){
    		if(sumb-b[i]<=suma&&flag-vis[i]==n-1){
    			fg=1;
    			break;
    		}
    	} 
    	if(fg) cout<<"YES\n";
    	else cout<<"NO\n"; 
    }
    
    signed main(){
    	ios::sync_with_stdio(0);
    	cin.tie(0);cout.tie(0);
    //  freopen("in.cpp","r",stdin);
    //  freopen("out.cpp","w",stdout);
    	int T=1;
    	cin>>T;
    //	clock_t start,finish;
    //	start=clock();
    	while(T--){
    		Solve();
    	}
    //	finish=clock();
    //	cerr<<((double)finish-start)/CLOCKS_PER_SEC<
    	return 0;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54

    L - The Firm Knapsack Problem

    背包问题,W是1e12。给定每个物品的体积和价值,然后问如果把W改成 3 W 2 \frac{3W}{2} 23W时的一个选择方案,使得该方案比能装入容量为W物品时的最优解价值更高。

    在原最优解的基础上随便筛入一个物品肯定是一个解,但是我们没办法得到原来的最优解。背包多出来了1/2的容量,那么可以按照这个大小划分两类物品,先在小于等于W/2的物品中贪心选取一组解,原最优解中大于W/2的物品不超过1个,那么我们枚举一下需要进行替换的大物品,就做完了。

    //#pragma GCC optimize("Ofast", "inline", "-ffast-math")
    //#pragma GCC target("avx,sse2,sse3,sse4,mmx")
    #include
    #define inf 0x3f3f3f3f
    #define int long long
    using namespace std;
    const int N=2e5+7;
    const int mod=1e9+7;
    
    //int read(){	int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-') f=f*-1;ch=getchar();}while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}return x*f;}
    //void write(int x){if(x>9) write(x/10);putchar(x%10+'0');}
    struct node{
    	double w,c,v,id;
    }s[N];
    
    bool cmp(int a,int b){return s[a].v>s[b].v;}
    int n,W,v1[N],v2[N],sumw[N],sumc[N];
    
    void Solve(){
    	cin>>n>>W; 
    	int cnt1=0,cnt2=0,res1=0,res2=0;
    	for(int i=1;i<=n;++i){
    		cin>>s[i].w>>s[i].c;
    		s[i].v=s[i].c/s[i].w;
    		s[i].id=i;
    		if(s[i].w*2<=W) v1[++cnt1]=i;
    		else v2[++cnt2]=i;
    	}
    	sort(v1+1,v1+1+cnt1,cmp);
    	for(int i=1;i<=cnt1;++i){
    		sumw[i]=sumw[i-1]+s[v1[i]].w;
    		sumc[i]=sumc[i-1]+s[v1[i]].c;
    	}
    	W=3*W/2;
    	for(int i=0;i<=cnt2;++i){
    		int pos=upper_bound(sumw,sumw+1+cnt1,W-s[v2[i]].w)-sumw;
    		if(pos>0&&s[v2[i]].c+sumc[pos-1]>res1){
    			res1=s[v2[i]].c+sumc[pos-1];
    			res2=i;
    		}
    	}
    	int pos = upper_bound(sumw,sumw+cnt1+1,W-s[v2[res2]].w)-sumw;
    	if(!pos){
    		cout<<"0\n";
    		return;
    	}
    	cout<<(res2?pos:pos-1)<<'\n';
    	if(res2) cout<<s[v2[res2]].id<<' ';
    	for(int i=1;i<pos;++i){
    		cout<<s[v1[i]].id<<' ';
    	}
    	cout<<'\n';
    }
    
    signed main(){
    	ios::sync_with_stdio(0);
    	cin.tie(0);cout.tie(0);
    //  freopen("in.cpp","r",stdin);
    //  freopen("out.cpp","w",stdout);
    	int T=1;
    	cin>>T;
    //	clock_t start,finish;
    //	start=clock();
    	while(T--){
    		Solve();
    	}
    //	finish=clock();
    //	cerr<<((double)finish-start)/CLOCKS_PER_SEC<
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70

    G - Cooking

    题意:给定n ( n ≤ 10 ) (n\le 10) (n10)个厨师可做的菜数、每道菜所需要做的次数 a i ( a i ≤ 50 ) a_i(a_i\le50) ai(ai50)。每次可以选两道菜并花 c i , j ( c i , j < 100 ) c_{i,j}(c_{i,j}<100) ci,j(ci,j<100)的时间去做,问最小需要的总时间,如果无解输出-1。

    思路:数据很小,拆成 ∑ a \sum a a个点然后两两做最小权匹配,套个带花树的板子即可。

    #include
    //#define int long long
    #define inf 0x3f3f3f3f
    using namespace std;
    const int N=805;
    
    int mp[550][550],a[55],b[550],sum,tot;
    
    struct E{
        int u,v,w;
        E(){};
        E(int u,int v,int w):u(u),v(v),w(w){}
    }g[N][N];
    int n,n_x;
    int lab[N];
    int match[N],slack[N],st[N],pa[N];
    int flower_from[N][N],S[N],vis[N];
    vector<int>flower[N];
    queue<int>q;
    
    inline int e_delta(const E &e){ // does not work inside blossoms
        return lab[e.u]+lab[e.v]-g[e.u][e.v].w*2;
    }
    
    inline void update_slack(int u,int x){
        if(!slack[x]||e_delta(g[u][x])<e_delta(g[slack[x]][x]))slack[x]=u;
    }
    inline void set_slack(int x){
        slack[x]=0;
        for(int u=1;u<=n;++u)
            if(g[u][x].w>0&&st[u]!=x&&S[st[u]]==0)update_slack(u,x);
    }
    void q_push(int x){
        if(x<=n)q.push(x);
        else for(size_t i=0;i<flower[x].size();i++)q_push(flower[x][i]);
    }
    inline void set_st(int x,int b){
        st[x]=b;
        if(x>n)for(size_t i=0;i<flower[x].size();++i)
                set_st(flower[x][i],b);
    }
    inline int get_pr(int b,int xr){
        int pr=find(flower[b].begin(),flower[b].end(),xr)-flower[b].begin();
        if(pr%2==1){//檢查他在前一層圖是奇點還是偶點
            reverse(flower[b].begin()+1,flower[b].end());
            return (int)flower[b].size()-pr;
        }else return pr;
    }
    
    inline void set_match(int u,int v){
        match[u]=g[u][v].v;
        if(u>n){
            E e=g[u][v];
            int xr=flower_from[u][e.u],pr=get_pr(u,xr);
            for(int i=0;i<pr;++i)set_match(flower[u][i],flower[u][i^1]);
            set_match(xr,v);
            rotate(flower[u].begin(),flower[u].begin()+pr,flower[u].end());
        }
    }
    
    inline void augment(int u,int v){
        for(;;){
            int xnv=st[match[u]];
            set_match(u,v);
            if(!xnv)return;
            set_match(xnv,st[pa[xnv]]);
            u=st[pa[xnv]],v=xnv;
        }
    }
    
    inline int get_lca(int u,int v){
        static int t=0;
        for(++t;u||v;swap(u,v)){
            if(u==0)continue;
            if(vis[u]==t)return u;
            vis[u]=t;//這種方法可以不用清空v陣列 
            u=st[match[u]];
            if(u)u=st[pa[u]];
        }
        return 0;
    }
    
    inline void add_blossom(int u,int lca,int v){
        int b=n+1;
        while(b<=n_x&&st[b])++b;
        if(b>n_x)++n_x;
        lab[b]=0,S[b]=0;
        match[b]=match[lca];
        flower[b].clear();
        flower[b].push_back(lca);
        for(int x=u,y;x!=lca;x=st[pa[y]])
            flower[b].push_back(x),flower[b].push_back(y=st[match[x]]),q_push(y);
        reverse(flower[b].begin()+1,flower[b].end());
        for(int x=v,y;x!=lca;x=st[pa[y]])
            flower[b].push_back(x),flower[b].push_back(y=st[match[x]]),q_push(y);
        set_st(b,b);
        for(int x=1;x<=n_x;++x)g[b][x].w=g[x][b].w=0;
        for(int x=1;x<=n;++x)flower_from[b][x]=0;
        for(size_t i=0;i<flower[b].size();++i){
            int xs=flower[b][i];
            for(int x=1;x<=n_x;++x)
                if(g[b][x].w==0||e_delta(g[xs][x])<e_delta(g[b][x]))
                    g[b][x]=g[xs][x],g[x][b]=g[x][xs];
            for(int x=1;x<=n;++x)
                if(flower_from[xs][x])flower_from[b][x]=xs;
        }
        set_slack(b);
    }
    
    inline void expand_blossom(int b){
        for(size_t i=0;i<flower[b].size();++i)
            set_st(flower[b][i],flower[b][i]);
        int xr=flower_from[b][g[b][pa[b]].u],pr=get_pr(b,xr);
        for(int i=0;i<pr;i+=2){
            int xs=flower[b][i],xns=flower[b][i+1];
            pa[xs]=g[xns][xs].u;
            S[xs]=1,S[xns]=0;
            slack[xs]=0,set_slack(xns);
            q_push(xns);
        }
        S[xr]=1,pa[xr]=pa[b];
        for(size_t i=pr+1;i<flower[b].size();++i){
            int xs=flower[b][i];
            S[xs]=-1,set_slack(xs);
        }
        st[b]=0;
    }
    inline bool on_found_edge(const E &e){
        int u=st[e.u],v=st[e.v];
        if(S[v]==-1){
            pa[v]=e.u,S[v]=1;
            int nu=st[match[v]];
            slack[v]=slack[nu]=0;
            S[nu]=0,q_push(nu);
        }else if(S[v]==0){
            int lca=get_lca(u,v);
            if(!lca)return augment(u,v),augment(v,u),true;
            else add_blossom(u,lca,v);
        }
        return false;
    }
    
    inline bool matching(){
        memset(S+1,-1,sizeof(int)*n_x);
        memset(slack+1,0,sizeof(int)*n_x);
        q=queue<int>();
        for(int x=1;x<=n_x;++x)
            if(st[x]==x&&!match[x])pa[x]=0,S[x]=0,q_push(x);
        if(q.empty())return false;
        for(;;){
            while(q.size()){
                int u=q.front();q.pop();
                if(S[st[u]]==1)continue;
                for(int v=1;v<=n;++v)
                    if(g[u][v].w>0&&st[u]!=st[v]){
                        if(e_delta(g[u][v])==0){
                            if(on_found_edge(g[u][v]))return true;
                        }else update_slack(u,st[v]);
                    }
            }
            int d=inf;
            for(int b=n+1;b<=n_x;++b)
                if(st[b]==b&&S[b]==1)d=min(d,lab[b]/2);
            for(int x=1;x<=n_x;++x)
                if(st[x]==x&&slack[x]){
                    if(S[x]==-1)d=min(d,e_delta(g[slack[x]][x]));
                    else if(S[x]==0)d=min(d,e_delta(g[slack[x]][x])/2);
                }
            for(int u=1;u<=n;++u){
                if(S[st[u]]==0){
                    if(lab[u]<=d)return 0;
                    lab[u]-=d;
                }else if(S[st[u]]==1)lab[u]+=d;
            }
            for(int b=n+1;b<=n_x;++b)
                if(st[b]==b){
                    if(S[st[b]]==0)lab[b]+=d*2;
                    else if(S[st[b]]==1)lab[b]-=d*2;
                }
            q=queue<int>();
            for(int x=1;x<=n_x;++x)
                if(st[x]==x&&slack[x]&&st[slack[x]]!=x&&e_delta(g[slack[x]][x])==0)
                    if(on_found_edge(g[slack[x]][x]))return true;
            for(int b=n+1;b<=n_x;++b)
                if(st[b]==b&&S[b]==1&&lab[b]==0)expand_blossom(b);
        }
        return false;
    }
    
    inline pair<long long,int> weight_blossom(){
        memset(match+1,0,sizeof(int)*n);
        n_x=n;
        int n_matches=0;
        long long tot_weight=0;
        for(int u=0;u<=n;++u)st[u]=u,flower[u].clear();
        int w_max=0;
        for(int u=1;u<=n;++u)
            for(int v=1;v<=n;++v){
                flower_from[u][v]=(u==v?u:0);
                w_max=max(w_max,g[u][v].w);
            }
        for(int u=1;u<=n;++u)lab[u]=w_max;
        while(matching())++n_matches;
        for(int u=1;u<=n;++u)
            if(match[u]&&match[u]<u)
                tot_weight+=g[u][match[u]].w;
        return make_pair(tot_weight,n_matches);
    }
    
    signed main(){
        scanf("%d",&n);
    	sum=0,tot=0;
        for(int i=1;i<=n;++i) scanf("%d",&a[i]),sum+=a[i];
        if(sum&1){
    		puts("-1");
    		return 0;
    	}
    	for(int i=1;i<=n;++i){
    		for(int j=1;j<=n;++j){
    			scanf("%d",&mp[i][j]);
    		}
    	}
    	for(int i=1;i<=n;++i){
    		for(int j=1;j<=a[i];++j){
    			b[++tot]=i;
    		}
    	}
    	for(int i=1;i<=tot;++i){
    		for(int j=1;j<=tot;++j){
    			g[i][j]=E(i,j,200-mp[b[i]][b[j]]);
    			g[j][i]=E(j,i,200-mp[b[j]][b[i]]);
    		}
    	}
    	n=sum;
        printf("%d\n",100*sum-weight_blossom().first);
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178
    • 179
    • 180
    • 181
    • 182
    • 183
    • 184
    • 185
    • 186
    • 187
    • 188
    • 189
    • 190
    • 191
    • 192
    • 193
    • 194
    • 195
    • 196
    • 197
    • 198
    • 199
    • 200
    • 201
    • 202
    • 203
    • 204
    • 205
    • 206
    • 207
    • 208
    • 209
    • 210
    • 211
    • 212
    • 213
    • 214
    • 215
    • 216
    • 217
    • 218
    • 219
    • 220
    • 221
    • 222
    • 223
    • 224
    • 225
    • 226
    • 227
    • 228
    • 229
    • 230
    • 231
    • 232
    • 233
    • 234
    • 235
    • 236
    • 237

    H - Hard Work

    问[a,b]中相同数字出现位数最多有多少个,有多少个数可以达到这个位数。

    一看题目就是数位DP,跟一般数位DP的形式一样,考虑每一位对答案的贡献,记录当前位置枚举的数字上界、以及有无前导0。

    //#pragma GCC optimize("Ofast", "inline", "-ffast-math")
    //#pragma GCC target("avx,sse2,sse3,sse4,mmx")
    #include
    #define inf 1e18
    #define int long long
    using namespace std;
    const int N=25;
    const int mod=1e9+7;
    
    //int read(){	int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-') f=f*-1;ch=getchar();}while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}return x*f;}
    //void write(int x){if(x>9) write(x/10);putchar(x%10+'0');}
    int dp[N][N][10][N][N],now;
    vector<int>tmp(25);
    
    inline int dfs(int pos,int lst,int len,int mx,bool lim,bool lead){
    	if(!pos) return mx>=now;
    	if(!lim&&!lead&&~dp[now][pos][lst][len][mx]){
    		return dp[now][pos][lst][len][mx];
    	}
    	int up=lim?tmp[pos]:9,res=0;
    	for(int i=0;i<=up;i++){
    		int p=lead?(i>0?1:0):(i==lst?len+1:1);
    		int mxx=max(mx,p);
    		res+=dfs(pos-1,i,p,mxx,lim&&i==up,lead&&i==0);
    	}
    	if(!lim&&!lead) return dp[now][pos][lst][len][mx]=res;
    	else return res;
    };
    
    inline int cal(int x){
    	if(!x) return 0;
    	int pos=0;
    	while(x) tmp[++pos]=x%10,x/=10;
    	return dfs(pos,0,0,0,1,1);
    };
    
    signed main(){
    //	ios::sync_with_stdio(0);
    //	cin.tie(0);cout.tie(0);
    //  freopen("in.cpp","r",stdin);
    //  freopen("out.cpp","w",stdout);
    	int T=1;
    //	cin>>T;
    //	clock_t start,finish;
    //	start=clock();
    	memset(dp,-1,sizeof(dp));
    	scanf("%lld",&T);
    	while(T--){
    		int a,b;	
    		scanf("%lld%lld",&a,&b);
    		for(int i=18;i>=1;--i){
    			int ans;now=i;
    			if(ans=cal(b)-cal(a-1)){
    				printf("%lld %lld\n",i,ans);
    				break;
    			}
    		}
    	}
    //	finish=clock();
    //	cerr<<((double)finish-start)/CLOCKS_PER_SEC<
    	return 0;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
  • 相关阅读:
    Apache Airflow (一) : Airflow架构及
    网络中的一些基本概念
    经过几年和前端调接口,我把抓包调试摸透了,浏览器岂非我对手
    pandas索引函数loc和iloc的区别
    1000万条数据分页方法,redis提高访问速度,减少数据库压力
    [附源码]Python计算机毕业设计django学生学习评价与分析系统
    2022年学Java开发的10个理由
    element级联选择器中el-cascader通过props自定义设置value、label、children
    python入门系列(1)—— 环境安装
    网络基础选择题
  • 原文地址:https://blog.csdn.net/SC_Linno/article/details/126057274