比赛传送门
作者: fn
背景
由于某些众所周知的原因,网络赛重赛了。所以这是网络赛“第一场”。
题目大意
有一条只有起点,没有终点,无限长的路。有无数的路灯,编号从1(起点)到无穷。 路灯是用电线连接的,有一条法则:
对于路灯x, 如果x是偶数,则 x x x 与 x 2 \frac{x}{2} 2x 用导线连接; 如果x是奇数,那么 x x x 和 3 x + 1 3x+1 3x+1 是用导线连接的。
站在路灯 n n n 和 n + 1 n+1 n+1 的中间,切断所有经过的电线。 也就是说,他将切断所有 a ≤ n a≤n a≤n 和 b > n b>n b>n 路灯a和b之间的连接线。计算切断电线的数量。
考察内容
数学
分析
对n左侧的所有x,分奇偶 O ( 1 ) O(1) O(1) 计算。
偶数x,数量为 ⌊ n + 1 2 ⌋ \lfloor \frac{n+1}{2} \rfloor ⌊2n+1⌋ 。
奇数x,第一根和n的右边有连接的 x 为 ⌊ n − 1 3 + 1 ⌋ \lfloor \frac{n-1}{3}+1 \rfloor ⌊3n−1+1⌋ ; 最后根据x的奇偶性分类讨论一下。
#include
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);
}
}
题目大意
有一种机器人可以通过接收一系列命令来移动。
命令序列中有四种类型的命令:
U:机器人向上移动一个单位。
D:机器人向下移动一个单位。
L:机器人向左移动一个单位。
R:机器人向右移动一个单位。
现在,给定一个长度为 n n n ( 2 ≤ n ≤ 1 0 5 2≤n≤10^5 2≤n≤105) 的命令序列。你需要找出命令序列中有多少连续子串,满足机器人执行子字符串命令时可以返回到起始位置。
考察内容
前缀和,map
分析
前缀和预处理当前位置出现的次数。向左右可以看作向上下走了1e6。
把每个位置当作子串结尾进行遍历,每次遍历到时,ans累计map之前的值。
最后输出ans即可。
#include
#include
#include
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;
}
题目大意
给定正数 n n n ,
求一个长度为 k ( 1 ≤ k ≤ n + 2 ) k(1≤k≤n+2) k(1≤k≤n+2) 的数组 a i ( a i ∈ { − 1 , 1 } ) {a_i}(a_i∈\{−1,1\}) ai(ai∈{−1,1}) ,使 ∑ i = 1 k a i × i 2 = n ∑_{i = 1}^k a_i×i^2 = n ∑i=1kai×i2=n
考察内容
思维,构造
分析
( x + 1 ) 2 − x 2 = 2 x + 1 (x+1)^2-x^2=2x+1 (x+1)2−x2=2x+1
( x + 3 ) 2 − ( x + 2 ) 2 = 2 x + 5 (x+3)^2-(x+2)^2=2x+5 (x+3)2−(x+2)2=2x+5
所以 ( x + 3 ) 2 − ( x + 2 ) 2 − ( x + 1 ) 2 + x 2 = 4 (x+3)^2-(x+2)^2-(x+1)^2+x^2=4 (x+3)2−(x+2)2−(x+1)2+x2=4
i ≥ 4 i≥4 i≥4时,构造 a i a_i ai 为 1 , − 1 , − 1 , 1 , . . . 1,-1,-1,1,... 1,−1,−1,1,... 的情况,就可以保证正确性。
#include
#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;
}
题目大意
给定一个小写字母组成的字符串,求最短的包含其中所有字母的连续子串的长度。
考察内容
双指针
分析
首先记录总字符个数。
跑一遍双指针。右指针指向子串末尾,不断右移。当出现的不同字符个数等于总字符个数时,更新答案,然后指向子串头部的左指针右移。
复杂度 O ( n ) O(n) O(n) 。
在双指针部分,注意控制一下边界情况,不要产生数组越界。
#include
#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;
}