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\n",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\n",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!\n");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\n",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!\n");continue;}
for(int i=1;i<=len;i++){
if(s[i]=='*') continue;
else printf("%c",s[i]);
}printf("\n");
}
}
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\n",Ans);
}
int main(){
int T=input();
while(T--)
Solve();
}