作者: fn

背景
由于某些众所周知的原因,网络赛重赛了。所以这是网络赛“第一场”。


目录

  • 签到题
  • 1001题 Cut The Wire / 切电线
  • 基本题
  • 1009题 Command Sequence / 指令序列
  • 1006题 Power Sum / 平方和
  • 1002题 Time-division Multiplexing / 时分多路转换



签到题

1001题 Cut The Wire / 切电线

题目大意
有一条只有起点,没有终点,无限长的路。有无数的路灯,编号从1(起点)到无穷。 路灯是用电线连接的,有一条法则:
对于路灯x, 如果x是偶数,则 trustaccess提示nc隧道连接失败 nc tcp_算法trustaccess提示nc隧道连接失败 nc tcp_算法_02 用导线连接; 如果x是奇数,那么 trustaccess提示nc隧道连接失败 nc tcp_算法trustaccess提示nc隧道连接失败 nc tcp_c++_04

站在路灯 trustaccess提示nc隧道连接失败 nc tcp_#include_05trustaccess提示nc隧道连接失败 nc tcp_算法_06 的中间,切断所有经过的电线。 也就是说,他将切断所有 trustaccess提示nc隧道连接失败 nc tcp_算法_07trustaccess提示nc隧道连接失败 nc tcp_子串_08

考察内容
数学

分析
对n左侧的所有x,分奇偶 trustaccess提示nc隧道连接失败 nc tcp_acm竞赛_09 计算。
偶数x,数量为 trustaccess提示nc隧道连接失败 nc tcp_#include_10
奇数x,第一根和n的右边有连接的 x 为 trustaccess提示nc隧道连接失败 nc tcp_子串_11

#include<bits/stdc++.h>
using namespace std;
long long n,ans=0,x,d;
int main()
{
    int t; scanf("%d",&t);
    while(t--)
    {
        ans=0;
        scanf("%lld",&n);
        ans=ans+(n+1)/2; // 偶数部分 
        
        // 奇数部分 
        x=(n-1)/3+1;
        if(x%2==1){
            ans+=(n-x)/2+1;
        }
        else{
            ans+=(n-x+1)/2;
        }
        printf("%lld\n",ans);
    }
}

基本题

1009题 Command Sequence / 指令序列

题目大意
有一种机器人可以通过接收一系列命令来移动。
命令序列中有四种类型的命令:
U:机器人向上移动一个单位。
D:机器人向下移动一个单位。
L:机器人向左移动一个单位。
R:机器人向右移动一个单位。

现在,给定一个长度为 trustaccess提示nc隧道连接失败 nc tcp_#include_05 ( trustaccess提示nc隧道连接失败 nc tcp_算法_13) 的命令序列。你需要找出命令序列中有多少连续子串,满足机器人执行子字符串命令时可以返回到起始位置。

考察内容
前缀和,map

分析
前缀和预处理当前位置出现的次数。向左右可以看作向上下走了1e6。
把每个位置当作子串结尾进行遍历,每次遍历到时,ans累计map之前的值。
最后输出ans即可。

#include <cstdio>
#include <cstring>
#include <map>
using namespace std;

map<long long,long long>m;
long long t,n,v,z,ans;
char c[200005];

int main() {
	scanf("%lld",&t);
	while(t--) {
		scanf("%lld",&n);
		scanf("%s",c);
		v=0;
		ans=0;
		m.clear();
		m[0]=1;
		for(int i=0;i<n;i++) {
			if(c[i]=='U') {
				z=1;
			} else if(c[i]=='D') {
				z=-1;
			} else if(c[i]=='L') {
				z=1e6; 
			} else if(c[i]=='R') {
				z=-1e6;
			}
			v+=z;
			ans+=m[v];
			
			m[v]=m[v]+1;
		}
		printf("%lld\n",ans);
	}
	return 0;
}

1006题 Power Sum / 平方和

题目大意
给定正数 trustaccess提示nc隧道连接失败 nc tcp_#include_05 ,
求一个长度为 trustaccess提示nc隧道连接失败 nc tcp_#include_15 的数组 trustaccess提示nc隧道连接失败 nc tcp_acm竞赛_16 ,使 trustaccess提示nc隧道连接失败 nc tcp_子串_17

考察内容
思维,构造

分析
trustaccess提示nc隧道连接失败 nc tcp_算法_18
trustaccess提示nc隧道连接失败 nc tcp_acm竞赛_19
所以 trustaccess提示nc隧道连接失败 nc tcp_acm竞赛_20
trustaccess提示nc隧道连接失败 nc tcp_c++_21时,构造 trustaccess提示nc隧道连接失败 nc tcp_算法_22trustaccess提示nc隧道连接失败 nc tcp_acm竞赛_23

#include<bits/stdc++.h>
#define ll long long
#define cer(x) cerr<<(#x)<<" = "<<(x)<<'\n'
using namespace std;
const int N=1e6+10;
ll n,m,a[N];
string s;
int main(){ 
	ios::sync_with_stdio(0); cin.tie(0);
	int t; cin>>t;
	while(t--){
		cin>>n;
		if(n%4==1){
			cout<<n<<endl;
			cout<<'1';
			for(int i=1;i<=n/4;i++){
				cout<<"1001";
			}
			cout<<endl;
		} 
		else if(n%4==2){
			cout<<n+2<<endl;
			cout<<"0001";
			for(int i=1;i<=n/4;i++){
				cout<<"1001";
			}
			cout<<endl;
		} 
		else if(n%4==3){
			cout<<n-1<<endl;
			cout<<"01";
			for(int i=1;i<=n/4;i++){
				cout<<"1001";
			}
			cout<<endl;
		} 
		else if(n%4==0){
			cout<<n<<endl;
			for(int i=1;i<=n/4;i++){
				cout<<"1001";
			}
			cout<<endl;
		} 
	}
	return 0;
}

1002题 Time-division Multiplexing / 时分多路转换

题目大意
给定一个小写字母组成的字符串,求最短的包含其中所有字母的连续子串的长度。

考察内容
双指针

分析
首先记录总字符个数。
跑一遍双指针。右指针指向子串末尾,不断右移。当出现的不同字符个数等于总字符个数时,更新答案,然后指向子串头部的左指针右移。
复杂度 trustaccess提示nc隧道连接失败 nc tcp_子串_24

在双指针部分,注意控制一下边界情况,不要产生数组越界。

#include<bits/stdc++.h>
#define ll long long
#define cer(x) cerr<<(#x)<<" = "<<(x)<<'\n'
using namespace std;
const int N=110;
ll n,m;
string s[N];
int len[N];

int num[27];
int has[27];
int kind=0,tp;

ll gcd(ll a, ll b){
    return b == 0 ? a : gcd(b, a % b);
}

void init(int n){
	memset(has,0,sizeof(has));
	memset(num,0,sizeof(num));
	memset(len,0,sizeof(len[0])*(n+1));
}

int main(){  
	ios::sync_with_stdio(0); cin.tie(0);
	int t; cin>>t;
	while(t--){
		cin>>n;
		init(n);
		
		for(int i=1;i<=n;i++){
			cin>>s[i];
			len[i]=s[i].size();
			for(int j=0;j<len[i];j++){
				int t1=s[i][j]-'a';
				has[t1]=1; //
			}
		}
		
		kind=0;
		for(int i=0;i<26;i++){
			if(has[i]) kind++;
		}
		
		ll high=1;
		for(int i=1;i<=n;i++){
			high=(high*len[i])/gcd(high,len[i]);
		}
		//	high<=27720,即(5*7*8*9*11)
		
		string str; // 
		for(int i=0;i<high;i++){ // 
			for(int j=1;j<=n;j++){
				int t2=i%len[j];
				str += s[j][t2];
			}
		}
		str+=str; // 两倍 
		
		ll ans=1e9+10;
		ll p1=0,p2=0; //
		int t3=str[p2]-'a';
		num[t3]++; //
		tp=1;
		
		int F1=0;
		
		int len2=high*n*2; //
		
		while(p1<len2 && p2<len2){ //
			if(tp==kind){ // 
				ans=min(ans,p2-p1+1);
				if(ans<=kind){ //
					cout<<ans<<endl;
					F1=1;
					break;
				}	
				
				int t4=str[p1]-'a';
				num[t4]--;
				if(num[t4]==0)tp--;
				
				p1++;
			}
			else{
				p2++;
				
				if(p2>=len2) break; // 防止数组越界 
				
				int t5=str[p2]-'a';
				if(num[t5]==0)tp++;
				num[t5]++;
			}
		}
		
		if(F1==0){
			cout<<ans<<endl;
		} 
	}
	return 0;
}