"Huawei Cup" the 15th undergraduate programming competition of Dalian University of Technology

Posted by phpcoder24july on Fri, 04 Mar 2022 04:33:58 +0100

M: A+B

Temporary sign in question

50: Mathematics

Please go in and ask for the sign in question

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> P;
int v;
int main(){
	puts("217341");
	return 0;
} 

H: Book

Check in question,

Note that if it is a string of identical letters, such as AAA, it can only be deleted

Otherwise, two letters appear, such as abba, abcba and ddz

If it's not a palindrome string, you obviously don't need to delete it;

Otherwise, just delete the last letter

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> P;
int T;
char s[205];
int cal(){
	bool sm=1;
	int n=strlen(s);
	for(int i=1;i<n;++i){
		sm&=(s[i]==s[i-1]);
	}
	if(sm)return n;
	for(int i=0;i<n;++i){
		if(s[i]!=s[n-1-i]){
			return 0;
		}
	}
	return 1;
}
int main(){
	scanf("%d",&T);
	while(T--){
		scanf("%s",s);
		printf("%d\n",cal());
	}
	return 0;
} 

A:  Lucky Number その1

Check in question, just count each number in the interval

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> P;
const int N=5e5+10;
int t,n,k,x,y;
int cal(int x){
	int c=0;
	for(;x;x/=10){
		if(x%10==4)c++;
		else{
			if(c==1 || c==2)return 0;
			c=0;
		}
	}
	if(c==1 || c==2)return 0;
	return 1; 
}
int main(){
	while(~scanf("%d%d",&x,&y)){
		if(x==-1 && y==-1)break;
		t++;
		assert(0<=x && x<=y && y<=100000);
		int ans=0;
		for(int i=x;i<=y;++i){
			ans+=cal(i);
		}
		printf("%d\n",ans);
	}
	assert(t<=6);
	return 0;
} 

E: Perfect array

Classified discussion, greedy, follow two principles,

1. Try to alternate positive and negative in the front, and use the one with more values at the beginning

2. Do not use zero in front. Try not to use zero. Zero can be placed in any position and block two values with the same symbol

#include<bits/stdc++.h>
using namespace std;
const int N=1e3+10;
int t,n,v,zero,ans[N];
vector<int>z,f;
bool solve(){
	int c=0;
	for(int i=1;i<=n;++i){
		if(c>=1){
			if(ans[c]>0){
				if(f.size()){
					int v=f.back();f.pop_back();
					ans[++c]=v;
				}
				else if(zero){
					zero--;
					ans[++c]=0;
				}
				else{
					return 0;
				}
			}
			else if(ans[c]<0){
				if(z.size()){
					int v=z.back();z.pop_back();
					ans[++c]=v;
				}
				else if(zero){
					zero--;
					ans[++c]=0;
				}
				else{
					return 0;
				}
			}
			else{
				if(!z.size() && !f.size()){
					zero--;
					ans[++c]=0;
				}
				else if(z.size()>f.size()){
					int v=z.back();z.pop_back();
					ans[++c]=v; 
				}
				else{
					int v=f.back();f.pop_back();
					ans[++c]=v;
				}
			}
		}
		else{
			if(!z.size() && !f.size()){
				zero--;
				ans[++c]=0;
			}
			else if(z.size()>f.size()){
				int v=z.back();z.pop_back();
				ans[++c]=v; 
			}
			else{
				int v=f.back();f.pop_back();
				ans[++c]=v;
			}
		}
	}
	return 1;
}
int main(){
	scanf("%d",&t);
	while(t--){
		scanf("%d",&n);
		zero=0;z.clear();f.clear();
		for(int i=1;i<=n;++i){
			scanf("%d",&v);
			if(v==0)zero++;
			else if(v<0)f.push_back(v);
			else z.push_back(v);
		}
		if(!solve())puts("NO");
		else{
			puts("YES");
			for(int i=1;i<=n;++i){
				printf("%d ",ans[i]);
			}
			puts("");
		}
	}
	return 0;
} 

G: Building blocks

Me: first sign in question

Miss Xia: really? Really? Really

The expected check-in question, but it doesn't seem to meet the expectation

Maybe it's because you may not have played icpc Kunming / Xuzhou

 

Note the fact that if the sum of [1,i] is greater than or equal to i+1, they can also add up the sum of [1,i+1]

Therefore, when k < = 2, the answer is k, otherwise it can be continuously annexed, which is sum-k+1

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> P;
int T,n,k;
int main(){
	scanf("%d",&T);
	while(T--){
		scanf("%d%d",&n,&k);
		if(k<=2)printf("%d\n",k);
		else printf("%lld\n",1ll*n*(n+1)/2-k+1);
	}
	return 0;
} 

C: High altitude wire rope

When there are only one or two people, one trip is enough,

Considering the situation of four people, when there are 1, 2, 3, 4 people (think 1 time is the shortest and 4 time is the longest),

Either 12 goes first, one time, 34 goes again, two times, and then there are only 12 left,

Either 14 goes first, one time, 13 goes again, one time, and then there are only 12 left

i-2 person scale recurs to i-2 person scale, so just make a dp

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e3+10;
int t,n,a[N];
ll dp[N];
int main(){
	scanf("%d",&t);
	assert(t<=100);
	while(t--){
		scanf("%d",&n);
		assert(n<=1000);
		for(int i=1;i<=n;++i){
			scanf("%d",&a[i]);
			assert(a[i]<=100000);
		}
		sort(a+1,a+n+1);
		dp[1]=a[1];dp[2]=a[2];
		for(int i=3;i<=n;++i){
			dp[i]=min(dp[i-1]+a[i]+a[1],dp[i-2]+a[2]+a[1]+a[i]+a[2]);
		}
		printf("%lld\n",dp[n]);
		//assert(dp[n]<=1ll<<32);
	}
	return 0;
} 

B: Lucky Number その2

Note the range 1e18, so only the digits dp

Maybe everyone's approach is different. The examiner's approach is,

It's not easy to do it directly, so consider subtracting the number of illegal schemes from the total,

Therefore, it is necessary to count the schemes with a length of 4 of 1 or a length of 4 of 2,

dp[i][j][0/1] indicates whether there are a number of schemes with a length of 1 or a length of 2 when j 4 are encountered continuously in bit I

Then, use the digital dp condom template to enumerate the number to be filled in. Will it affect the continuous 4? Is there a 4 with length of 1 or a 4 with length of 2

True warrior, dare to write B first and then A

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> P;
const int N=5e5+10;
ll x,y,a[20],dp[20][20][2];
ll dfs(int x,int four,bool has,bool up){
	//printf("x:%d four:%d has:%1d up:%1d\n",x,four,has,up);
	if(x==0){
		return has==1 || four==1 || four==2;
	}
	if(!up && ~dp[x][four][has]){
		return dp[x][four][has];
	}
	ll ans=0;
	int lim=up?a[x]:9;
	for(int i=0;i<=lim;++i){
		if(four==1 || four==2){
			if(i==4){
				ans+=dfs(x-1,four+1,has,up && i==lim);
			}
			else{
				ans+=dfs(x-1,0,1,up && i==lim);
			}
		}
		else{
			if(i==4){
				ans+=dfs(x-1,four+1,has,up && i==lim);
			}
			else{
				ans+=dfs(x-1,0,has,up && i==lim);
			}
		}
	}
	if(!up)dp[x][four][has]=ans;
	//printf("x:%lld four:%lld has:%lld dp:%lld\n",x,four,has,dp[x][four][has]);
	return ans;
}
ll cal(ll x){
	if(x<=0)return 0;
	int c=0;
	for(;x;x/=10){
		a[++c]=x%10;
	}
	memset(dp,-1,sizeof dp);
	return dfs(c,0,0,1);
}
int main(){
	while(~scanf("%lld%lld",&x,&y)){
		if(x==-1 && y==-1)break;
		ll n=y-x+1,ill=cal(y)-cal(x-1);
		//printf("n:%lld ill:%lld",n,ill);
		printf("%lld\n",n-ill);
	}
	return 0;
} 

J: Cat

Author: look at this question

Me: This is not the original question, hdu6187

Author: No, it's from Japan icpc2010

So the person who made the question didn't repent, and may make it again next time

 

Consider the minimum to be removed, so the maximum to be retained,

The reserved part has no ring, so it is to find a maximum spanning tree

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> P;
const int N=1e4+10,M=3e4+10;
int n,m;
int par[N];
P a[N];
double sum,ans;
int find(int x){
	return par[x]==x?x:par[x]=find(par[x]);
}
struct node{
	int u,v;
	double w;
}e[M];
bool operator<(node a,node b){
	return a.w>b.w; 
};
double sq(double x){
	return x*x; 
}
double cal(P a,P b){
	return sqrt(sq(a.first-b.first)+sq(a.second-b.second));
}
int main(){
	scanf("%d%d",&n,&m);
	//if(n==10000)while(1); 
	assert(1<=n && n<=10000);
	assert(1<=m && m<=30000);
	for(int i=1;i<=n;++i){
		par[i]=i;
		scanf("%d%d",&a[i].first,&a[i].second);
		assert(-10000<=a[i].first && a[i].first<=10000);
		assert(-10000<=a[i].second && a[i].second<=10000);
	}	
	for(int i=1;i<=m;++i){
		scanf("%d%d",&e[i].u,&e[i].v);
		assert(1<=e[i].u && e[i].u<=n);
		assert(1<=e[i].v && e[i].v<=n);
		assert(e[i].u!=e[i].v);
		e[i].w=cal(a[e[i].u],a[e[i].v]);
	}
	sort(e+1,e+m+1);
	for(int i=1;i<=m;++i){
		int u=find(e[i].u),v=find(e[i].v);
		sum+=e[i].w;
		if(u==v)continue;
		par[v]=u;ans+=e[i].w;
	}
	printf("%.10lf\n",sum-ans);
	return 0;
} 

K: Draw

First assume that everything is done by yourself, and then consider what can be flipped,

If you copy the j-th time on the i-th day, you can complete the (i-1)-(j-1) times by yourself, and finally get the benefit of (2*(j-1)-(i-1)+P)*Q,

Compared with self completion, the additional income is (2*(j-1)-(i-1)+P)*Q-c[i]=2*(j-1)*Q+P*Q-(i-1)*Q-c[i]

Note that after i and j are separated, the contributions can be counted separately,

Considering that the enumeration is copied j times, the sum of 2*(j-1)*Q is fixed,

Only the top j largest - (i-1)*Q-c[i] is required, which can be sorted

 

It's a practice that comes out only after being educated by the author,

At the beginning, I copied everything first, and then reversed dp[i] maintenance suffix. I copied the maximum profit for I days

Isn't copying homework happy

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> P;
const int N=5e5+10;
int n,p,q,c[N],id[N];
ll ans,tmp;
bool cmp(int x,int y){	
	return 1ll*(x-1)*p+c[x]<1ll*(y-1)*p+c[y];
}
int main(){
	scanf("%d%d%d",&n,&p,&q);
	assert(1<=n && n<=500000);
	assert(0<=p && p<=500000);
	assert(abs(q)<=500000);
	for(int i=1;i<=n;++i){
		scanf("%d",&c[i]);
		assert(abs(c[i])<=500000);
		tmp+=c[i];
		id[i]=i;
	}
	sort(id+1,id+n+1,cmp);
	ans=tmp;
	for(int j=1;j<=n;++j){
		tmp-=1ll*(id[j]-1)*p+c[id[j]];
		tmp+=2ll*(j-1)*p+1ll*p*q;
		ans=max(ans,tmp);
	}
	printf("%lld\n",ans);
	return 0;
} 

F: Perfect number pair

It is said that the interview question of wechat is cleverly constructed,

But I won't, which fully reflects the lack of brain,

No brain, everyone

 

First, notice that k > C (n, 2) must have no solution, otherwise there must be a solution,

If we can find that 2*i is a complete square, 2*j is a complete square, and i+j is a complete square

Then a total of x i and j are placed, X points are a group (two sides), and the contribution is x*(x-1)/2

Here, a group of (i,j)=(2,98) is found by typing the table,

 

Find the maximum x satisfying x * (x-1) / 2 < = k, and then there are k-x*(x-1)/2 edges left

If k-x*(x-1)/2=0, just put the value that will not affect the answer,

Otherwise, a value that can be connected with 2 is determined, and the number of 2 is determined

At this time, if there is more, just put it casually, which will not affect the value of the answer

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> P;
const int N=5e5+10;
int t,n,k,x,y;
int main(){
	scanf("%d",&t);
	while(t--){
		scanf("%d%d",&n,&k);
		if(k>n*(n-1)/2){
			puts("No");
			continue;
		} 
		puts("Yes");
		for(x=0;x*(x-1)/2<=k;++x);x--;
		y=k-x*(x-1)/2;
		if(!y){
			for(int i=1;i<=x;++i){
				printf("%d ",2);
			}	
			for(int i=1;i<=n-x;++i){
				printf("%d ",3);
			}
		}
		else{
			for(int i=1;i<=y;++i)printf("%d ",2);
			for(int i=1;i<=x-y;++i)printf("%d ",98);
			printf("%d ",223);
			for(int i=1;i<=n-x-1;++i)printf("%d ",1);
		}
		puts("");
	}
	return 0;
} 

D: Square count

The examiner is O(n^2logn) who fooled around. I always like data structures jpg

The official solution has the practice of O(n^2), I don't listen, I don't listen, I don't listen, I don't listen

 

Inspired by the example,

First, l, r, u and d maintain the same expandable length on the left, right, up and down respectively,

Then consider how to count the answers. Here is the enumeration diagonal from top left to bottom right,

Consider that point B maintains A left-hand upward shell and point A inserts A right-hand downward shell,

If A can cover B and B can cover A, and the AB value is the same, it is A legal square,

So consider the parallel lines of each diagonal and open a tree array

For all sorts on the same line, the first keyword is value and the second keyword is location,

 

Take all the same values, insert them first, then count the answers, and then cancel them

Note that the position of A is pos on the same line, and the range of cover to the right and down is [pos,pos+v-1] (segment 1)

Where v is the length of the short side of both right and down,

Then the position of B is pos2, and the range of cover to the left is [pos2-w+1,pos2] (segment 2)

Where w is the length of the short side of both left and up,

A. B forms a legal square if and only if segment 1 covers pos2 and segment 2 covers pos1

 

This is a classic question, and the approach here is,

First insert A at pos and undo it at pos+v (A priority queue is used here)

Then, when B passes, count the number of schemes of values in the interval

#include<bits/stdc++.h>
using namespace std;
typedef pair<int,int> P;
const int N=1e3+10,M=2e3+5,off=1e3;
int tr[M][N],l[N][N],r[N][N],u[N][N],d[N][N];
int n,m,a[N][N],ans;
priority_queue<P,vector<P>,greater<P> >q;
void add(int id,int x,int v){
	for(int i=x;i<N;i+=i&-i){
		tr[id][i]+=v;
	}
} 
int sum(int id,int x){
	if(x<=0)return 0;
	int ans=0;
	for(int i=x;i>0;i-=i&-i){
		ans+=tr[id][i];
	}
	return ans;
}
struct node{
	int id,x,y,v;
}e[N];
bool cmp(node a,node b){
	return a.v<b.v || (a.v==b.v && a.id<b.id);
}
int main(){
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;++i){
		for(int j=1;j<=m;++j){
			scanf("%d",&a[i][j]);
			l[i][j]=(a[i][j]==a[i][j-1]?l[i][j-1]+1:1);
			u[i][j]=(a[i][j]==a[i-1][j]?u[i-1][j]+1:1);
		}
	}
	for(int i=n;i>=1;--i){
		for(int j=m;j>=1;--j){
			r[i][j]=(a[i][j]==a[i][j+1]?r[i][j+1]+1:1);
			d[i][j]=(a[i][j]==a[i+1][j]?d[i+1][j]+1:1);
		}
	}
	for(int dig=1-n;dig<=m-1;++dig){
		int i,j,c=0,id=dig+off;
		if(dig<=0)j=1,i=j-dig;
		else i=1,j=i+dig;
		for(;i<=n&&j<=m;++i,++j){
			++c;
			e[c]={c,i,j,a[i][j]};
		}
		sort(e+1,e+c+1,cmp);
		for(int x=1;x<=c;){
			int y=x;
			while(y+1<=c && e[y+1].v==e[x].v){
				y++;
			}
			for(int z=x;z<=y;++z){
				i=e[z].x,j=e[z].y;
				int pos=min(i,j);
				int w=min(l[i][j],u[i][j]);
				int v=min(r[i][j],d[i][j]);
				while(!q.empty() && q.top().first<=pos){
					int r=q.top().second;q.pop();
					add(id,r,-1);
				}
				add(id,pos,1);
				//printf("a:%d b:%d\n",sum(id,pos),sum(id,pos-w));
				q.push(P(pos+v,pos));
				int more=sum(id,pos)-sum(id,pos-w); 
				//printf("w:%d\n",w);
				ans+=more;
				//printf("i:%d j:%d more:%d\n",i,j,more);
			}
			while(!q.empty()){
				int r=q.top().second;q.pop();
				add(id,r,-1);
			}
			x=y+1;
		}
	}
	printf("%d\n",ans);
	return 0;
}

1: Chess

The examiner will not. The positioning given is to prevent AK problems. You can refer to the official problem solution

The general idea is to turn Manhattan distance into Chebyshev distance first

Then consider maintaining a four-dimensional dp,

Xmax, Ymin, XMI, YM,

Add one row or column of statistical contributions at a time

 

The contribution of the test subjects and make complaints about them

Fixed the bug of perfect array spj,

Fixed the bug of the number of samples of the perfect array and the character length of the book

They have engaged in a number of violent and false practices and have not broken through,

The structure made a cross-border and didn't fuck the past,

Good guy, all of them have been prevented. There's no pot

 

In my opinion, the author has produced a set of good questions without template questions, which are highly praised~

 

The students who are responsible for planning, arranging, invigilating, writing and testing questions in the main campus and soft college have worked hard~

The students also worked hard~