2020 Multi-University Training Contest 3 解题报告

1004


计算取模后的前缀和,并且存到map里,然后每次在map里查找是否有相同的数,有则答案加一,清空前缀和和map,没有则继续往后找。不过要提前把是k的倍数加到答案里,上面遇到0直接结束,清空map,查找下一段。

#include <bits/stdc++.h>

using namespace std;

#define ll long long
ll input(){
	ll x=0,f=0;char ch=getchar();
	while(ch<'0'||ch>'9') f|=ch=='-',ch=getchar();
	while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
	return f? -x:x;
}

const int N=2e5+7;

ll n,p;
ll a[N];
map <ll,int> mp;

int main(){
	int T=input();
	while(T--){
		n=input(),p=input();
		ll Ans=0;
		for(int i=1;i<=n;i++){
			a[i]=input()%p;
			if(!a[i]) Ans++;
		}

		ll sum=0;
		for(int i=1;i<=n;i++){
			if(a[i]==0){
				mp.clear();sum=0;
				continue;
			}
			sum=(sum+a[i])%p;
			if(sum==0){Ans++;sum=0;mp.clear();}
			else if(mp[sum]>=1){Ans++;sum=0;mp.clear();}
			else mp[sum]++;
		}


		printf("%lld
",Ans);
	}
}

1009

温暖的签到。首先用栈匹配')'的括号,优先匹配靠前的'*',再梅开二度用栈匹配'(',优先匹配靠后'*',然后其它的‘*’都是空的。

#include <bits/stdc++.h>

using namespace std;

#define ll long long
ll input(){
	ll x=0,f=0;char ch=getchar();
	while(ch<'0'||ch>'9') f|=ch=='-',ch=getchar();
	while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
	return f? -x:x;
}

const int N=3e5+7;

char s[N];
vector <int> star;
stack <int> st1,st2;

int main(){
	int T=input();
	while(T--){
		while(!st1.empty()) st1.pop();
		while(!st2.empty()) st2.pop();
		scanf("%s",s+1);
		int len=strlen(s+1);

		star.clear();
		for(int i=1;i<=len;i++){
			if(s[i]=='*') star.push_back(i);
		}

		for(int i=len;i>=1;i--){
			if(s[i]==')') st2.push(i);
			if(s[i]=='('&&!st2.empty()) st2.pop(); 
		}

		// while(!st2.empty()) printf("%d
",st2.top()),st2.pop();

		int flag=0;
		for(int j=0;j<star.size();j++){
			if(st2.empty()) break;
			if(st2.top()<star[j]) {flag=1;break;}
			s[star[j]]='(';st2.pop();
		}

		if(!st2.empty()||flag==1){printf("No solution!
");continue;}

		star.clear();
		for(int i=len;i>=1;i--){
			if(s[i]=='*') star.push_back(i);
		}

		for(int i=1;i<=len;i++){
			if(s[i]=='(') st1.push(i);
			if(s[i]==')'&&!st1.empty()) st1.pop();
		}
		// while(!st1.empty()) printf("%d
",st1.top()),st1.pop();

		flag=0;
		for(int j=0;j<star.size();j++){
			if(st1.empty()) break;
			if(st1.top()>star[j]) {flag=1;break;}
			s[star[j]]=')';st1.pop();
		}
		if(!st1.empty()||flag==1){printf("No solution!
");continue;}

		for(int i=1;i<=len;i++){
			if(s[i]=='*') continue;
			else printf("%c",s[i]);
		}printf("
");
	}
}

1007

非传统结论题。因为边权随机,所有最短路最长为3,直接dfs枚举最短路上边,问题转化为去掉(k-1)条边的答案。

#include <bits/stdc++.h>

using namespace std;
#define ll long long
ll input(){
	ll x=0,f=0;char ch=getchar();
	while(ch<'0'||ch>'9') f|=ch=='-',ch=getchar();
	while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
	return f? -x:x;
}

const ll N = 2507;
const ll INF = 0x3f3f3f3f3f3f3f;
ll mp[N][N],vis[N*N],dis[N*N],head[N*N],path[10][N];

ll n,k;
ll Ans=0;
void spfa(int fg,int dep){
	for(int i=0;i<=n;i++){
		vis[i] = 0;dis[i] = INF;
	}
	queue <ll> q;
	q.push(1);dis[1] = 0;
	while(!q.empty()){
		ll x = q.front();q.pop();vis[x] = 0;
		for(int i=1;i<=n;i++)
		if(mp[x][i]!=INF&&dis[i]>dis[x]+mp[x][i]){
			dis[i] = dis[x]+mp[x][i];
			if(fg==0) path[dep][i] = x; 
			if(vis[i]==0){
				vis[i] = 1;
				q.push(i);
			}
		}
	}
}

void dfs(int dep){
	if(dep==0){spfa(1,dep); Ans=max(Ans,dis[n]); return;}
	spfa(0,dep);

	for(int i=n;path[dep][i]!=0;i=path[dep][i]){
		ll tp = mp[path[dep][i]][i];
		mp[path[dep][i]][i] = mp[i][path[dep][i]] = INF;
		dfs(dep-1);
		mp[path[dep][i]][i] = mp[i][path[dep][i]] = tp;
	}
}

void Solve(){
	n=input(),k=input();
	for(int i=0;i<=n;i++){
		for(int j=0;j<=n;j++) mp[i][j] = INF;
	}
	for(int i=1;i<=(n*(n-1))/2;i++){
		ll x=input(),y=input(),z=input();
		mp[x][y] = mp[y][x] = z;
	}
	
	Ans=0;
	dfs(k);

	printf("%lld
",Ans);
}

int main(){
	int T=input();
	while(T--)
		Solve();
}
原文地址:https://www.cnblogs.com/-aether/p/13397498.html