湖南大学2021届ACM新生赛【题目全解】——补题ing

牛客已经开过重现赛了,想挑战的朋友可以去看看ヾ(◍°∇°◍)ノ゙
比赛传送门:重现赛

A题

题面:

在这里插入图片描述
在这里插入图片描述

题解:

BF解法

#include<bits/stdc++.h>
using namespace std;
const int mod=1e9+7;
int main() {
	int n;
	cin>>n;
	assert(1<=n&&n<=1000000);//断言n>=1且n<=1000000,否则程序终止
	int res=1;
	for(int i=0;i<n;i++) res=res*2%mod;
	cout<<res-1;
	return 0;
}

qspow解法

#include<iostream>
using namespace std;
const long long c=1e9+7;
typedef long long ll;
ll mypow(int a,int k){
    if(k==0)return 1;
    a%=c;
    if(k&1)return (a*mypow(a,k-1))%c;
    else{
        ll sub=mypow(a,k>>1);
        return (sub*sub)%c;  //标准的二分快速幂
    }
}
int main(){
    ll b;
    cin>>b;
    ll jie=mypow(2,b)-1;
    cout<<jie<<endl;
    return 0;
}

反思:

一眼就看出来杨辉三角,2^n-1
这题是作为签到题出的,可我居然耗了差不多一个半小时还没写出来。
说实话,我至今都还没想明白:为什么我这道签到题花了这么久还没做出来
我记得,我第一次是这样提交的:

#include<iostream>
using namespace std;
const long long c=1e9+7;
typedef long long ll;
ll mypow(ll k){
    if(k==0)return 1;
    if(k&1)return (2*mypow(k-1))%c;
    else{
        return mypow(k>>1)%c*mypow(k>>1)%c;
    }
}
int main(){
    ll b;
    cin>>b;
    ll jie=mypow(b)-1;
    cout<<jie<<endl;
    return 0;
}

[注:这段代码在重现赛上能过]
回顾:当时直接快速幂上去,以为能一遍秒过,结果惊奇地WA。(可能当时某些地方写错了吧,而我一直没发现)一遍一遍地二分快速幂,一遍一遍地改,甚至还自定义二分形式的乘法来防溢出,一遍一遍的WA,我感觉那段时间我完全在摸鱼,很着急,却一直写错。
当时,完全想的是二分快速幂是怎么错的,居然连BF解法都没试过
下场后重写,居然又完全没错了🤔。牛客回顾是一遍过啊
应该是我在打比赛时状态出问题了,这应该是所谓压力编程吧。
我还专门写过二分快速幂的文章——
《星空解题家》:二分快速幂——何为二分快速幂?二分思想解题
当然,比赛结束前半个小时还在看签到题的我~~~
很遗憾地只水了个银奖[ಥ_ಥ]

B题

题面:

在这里插入图片描述

题解:

补解:

#include<iostream>
#include<cmath>
using namespace std;
#define ll long long
int main(){
    int t;
    scanf("%d",&t);
    while(t--){
    ll a,b,c,d;
    cin>>a>>b>>c>>d;
    ll e=a*d+b*c,f=llabs(a*c-b*d);
    if(!f){
        e=llabs(a*d-b*c);
        f=a*c+b*d;
    }
    printf("%lld %lld\n",e,f);
    }
    return 0;
}

官解:

#include<bits/stdc++.h>
using namespace std;
int main() {
  #ifdef Sakuyalove
    freopen("in.in", "r", stdin);
    freopen("out.out", "w", stdout);
  #endif
  int T;
  cin >> T;
  assert(1 <= T && T <= (int)1e4);
  while (T--) {
    long long a, b, c, d;
    cin >> a >> b >> c >> d;
    assert(1 <= a && a <= (int)(1e9));
    assert(1 <= b && b <= (int)(1e9));
    assert(1 <= c && c <= (int)(1e9));
    assert(1 <= d && d <= (int)(1e9));
    assert(a != b || c != d);
    assert(a * d != b * c || a * c != b * d);
    long long e = llabs(a * c - b * d), f = a * d + b * c;
    if (e == 0) {
	  e = llabs(a * d - b * c), f = a * c + b * d;
      assert(1 <= e && e <= (long long)4e18 && 1 <= f && f <= (long long)4e18);
      assert((__int128)(a * a + b * b) * (__int128)(c * c + d * d) == ((__int128)e * e + (__int128)f * f));
      cout << e << ' ' << f << endl;
    }
    else {
      assert(1 <= e && e <= (long long)4e18 && 1 <= f && f <= (long long)4e18);
      assert((__int128)(a * a + b * b) * (__int128)(c * c + d * d) == ((__int128)e * e + (__int128)f * f));
      cout << e << ' ' << f << endl;
    }
  }
  return 0;
}

分析:

在这里插入图片描述

在这里插入图片描述

反思:

这道题是比较简单的,只交三次就过了。



C题

题面:

在这里插入图片描述

题解:

补解:

#include<iostream>
using namespace std;
typedef long long ll;
int main(){
    int t;
    scanf("%d",&t);
    while(t--){
        ll x1,y1,x2,y2;
        cin>>x1>>y1>>x2>>y2;
        ll A,B,C;
        cin>>A>>B>>C;
        int j1,j2;
        if(A*x1+B*y1+C>0)j1=1;
        else j1=-1;
        if(A*x2+B*y2+C>0)j2=1;
        else j2=-1;
        if(j1*j2==1)cout<<"Yes"<<endl;
        else cout<<"No"<<endl;
    }
    return 0;
}

官解:

在这里插入代码片

反思:

直接过,签到。so easy

D题

题面:

在这里插入图片描述
在这里插入图片描述

题意|分析:

关键思想:二维前缀和

在一个n*m的网格中,每个格点都有个权值,q个询问,形式为(r,c,d)表示距离点(r,c)d以内的所有点的权值和是多少?(曼哈顿距离)
1<=r<=n<=2000;
1<=c<=m<=2000;
d,q<=1e6;
点权<=1e9
像这样:
在这里插入图片描述
很明显,每次查询,直接暴力地找出对应各点求和是一定会超时的。所以我们很容易想到【前缀和】,不过这里前缀和换到了二维

——如果每次询问是个正着摆的正方形,那我们可以直接二维前缀和维护
斜着的咋办?我们可以把网格图也一起斜着摆!
——事实上,我们可以构造一个与网格图中心重合的大正方形来恰好“框柱”原来的网格图,那么,在原图上询问的斜着的正方形就可以转化成新图中正着的正方形
——在新构造的图上维护二维前缀和即可
在这里插入图片描述

题解:

[1]:补解:


[2]官解:

//在一个n*m的网格中,每个格点都有个权值,q个询问,形式为(x,y,d)表示距离点(x,y)d以内的所有点的权值和是多少(曼哈顿距离)
//n,m<=2000,q<=1e6
#include<bits/stdc++.h>
using namespace std;
int n,m,q,d;
int val[4005][4005];
long long f[4005][4005];
inline int read()
{
	int X=0,Y=1;char C=getchar();
	while (C<'0'||C>'9') {if (C=='-') Y=-1;C=getchar();}
	while (C>='0'&&C<='9') X=X*10+C-'0',C=getchar();
	return X*Y;
}
int main()
{
    memset(val,0,sizeof(val));
    memset(f,0,sizeof(f));
    n=read();m=read();q=read();
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
            val[i+j-1][n+j-i]=read();
    for(int i=1;i<=n+m-1;i++)
        for(int j=1;j<=n+m-1;j++)
            f[i][j]=f[i-1][j]+f[i][j-1]-f[i-1][j-1]+1ll*val[i][j];
    for(int i=1;i<=q;i++)
    {
        int r,c,d;
        r=read();c=read();d=read();
		int lr=max(0,r+c-d-2),lc=max(0,n+c-r-d-1),rr=min(n+m-1,r+c+d-1),rc=min(n+m-1,n+c-r+d);
		printf("%lld\n",f[rr][rc]-f[lr][rc]-f[rr][lc]+f[lr][lc]);
    }
    return 0;
}


E题

题面:

在这里插入图片描述

题意|分析:

在这里插入图片描述

题解:

[1]补解:

#include<iostream>
using namespace std;
typedef long long LL;
const int N=1e7+10,mod=998244353;
int k,q,l,r;
int cnt,prime[N];
LL f[N];
bool st[N];
int qmi(int a,int k,int p)
{
    int res=1;
    while(k)
    {
        if(k&1) res=(LL)res*a%p;
        k>>=1;
        a=(LL)a*a%p;
    }
    return res;
}
void init()
{
    f[1]=1;
    for(int i=2;i<N;i++)
    {
        if(!st[i])
        {
            prime[cnt++]=i;
            f[i]=qmi(i,k,mod)%mod;
        }
        for(int j=0;prime[j]*i<N;j++)
        {
            int t=prime[j]*i;
            st[t]=true;
            f[t]=f[i]*f[prime[j]]%mod;
            if(i%prime[j]==0) break;
        }
    }
    for(int i=1;i<N;i++) f[i]+=f[i-1];
}
int main()
{
    scanf("%d%d",&k,&q);
    init();
    while(q--)
    {
        scanf("%d%d",&l,&r);
        printf("%d\n",(f[r]-f[l-1]+mod)%mod);
    }
    return 0;
}

[2]官解:

#include<bits/stdc++.h>
using namespace std;

const int M = 1e7;
const int mod = 998244353;

int qpow(int a, int p) {
  int ret = 1;
  while (p) {
    if (p & 1) ret = 1ll * a * ret % mod;
    a = 1ll * a * a % mod;
    p >>= 1;
  }
  return ret;
}

bool np[M + 5];
int p[M + 5], num, s[M + 5];
int k, q;

signed main() {
  #ifdef Sakuyalove
    freopen("in.in", "r", stdin);
    freopen("out.out", "w", stdout);
  #endif
  cin >> k >> q;
  s[1] = 1;
  for (int i = 2; i <= M; i++) {
    if (!np[i]) {
      p[++num] = i;
      s[i] = qpow(i, k);
    }
    for (int j = 1; j <= num; j++) {
      if (1ll * p[j] * i > M) break;
      np[p[j] * i] = 1;
      s[p[j] * i] = 1ll * s[p[j]] * s[i] % mod;
      if (i % p[j] == 0) break;
    }
  }
  for (int i = 1; i <= M; i++) s[i] = (s[i - 1] + s[i]) % mod;
  while (q--) {
    int l, r;
    cin >> l >> r;
    cout << (s[r] - s[l - 1] + mod) % mod << endl;
  }
  return 0;
}




F题

题面:

在这里插入图片描述

在这里插入图片描述

题意|分析:

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

题解:

[1]补解:

#include<iostream>
#include<cstring>
using namespace std;
const int N=1100;
int g[5][30]={
    {1,2,7,8,13,14,19,20,25,26,31,32,37,38,0,4,5,10,11,16,17,22,23,28,29,34,35,40},
    {0,3,6,11,13,14,16,21,24,29,31,32,34,39,2,4,5,7,12,15,20,22,23,25,30,33,38,40},
    {5,7,9,11,13,14,16,18,20,22,33,35,37,39,0,6,8,10,12,15,17,19,21,32,34,36,38,40},
    {0,15,17,19,21,23,25,27,29,31,33,35,37,39,14,16,18,20,22,24,26,28,30,32,34,36,38,40}    
};
int cnt[N];
bool st[N];
int main()
{
    string s;
    while(cin>>s)
    {
        memset(st,false,sizeof st);
        memset(cnt,0,sizeof cnt);
        int ans=0;
        for(int i=0;i<4;i++)
        {
            if(s[i]=='=') 
            {
                for(int j=0;j<28;j++) st[g[i][j]]=true;
            }
            else if(s[i]=='<')
            {
                for(int j=0;j<14;j++) cnt[g[i][j]]--;
                for(int j=14;j<28;j++) cnt[g[i][j]]++;
                ans++;
            }
            else if(s[i]=='>')
            {
                for(int j=0;j<14;j++) cnt[g[i][j]]++;
                for(int j=14;j<28;j++) cnt[g[i][j]]--;
                ans++;
            }
        }
        int flag=0;
        for(int i=0;i<4;i++)
        {
            for(int j=0;j<28;j++)
            {
                if(!st[g[i][j]])
                {
                    if(cnt[g[i][j]]==ans) 
                    {
                        cout<<g[i][j]<<" heavy"<<endl;
                        flag=1;
                        break;
                    }
                    else if(cnt[g[i][j]]==-ans) 
                    {
                        cout<<g[i][j]<<" light"<<endl;
                        flag=1;
                        break;
                    }
                }
            }
            if(flag) break;
        }

    }
    return 0;
}

[2]官解.C语言:

解法一:
#include<stdio.h>
int wt[4][28]={{1,2,7,8,13,14,19,20,25,26,31,32,37,38,0,4,5,10,11,16,17,22,23,28,29,34,35,40},
               {0,3,6,11,13,14,16,21,24,29,31,32,34,39,2,4,5,7,12,15,20,22,23,25,30,33,38,40},
			   {5,7,9,11,13,14,16,18,20,22,33,35,37,39,0,6,8,10,12,15,17,19,21,32,34,36,38,40},
			   {0,15,17,19,21,23,25,27,29,31,33,35,37,39,14,16,18,20,22,24,26,28,30,32,34,36,38,40}};
int check(int t,int k,int j,char c){
	int i,f,r;
	for(i=f=0;!f&&i<14;++i)if(wt[t][i]==k)f=-1;
	for(;!f&&i<28;++i)if(wt[t][i]==k)f=1;
	if(c=='=')r=0;else if(c=='>')r=-1;else r=1;
	return j*f==r;
}

int main(){
	int i,j,k,f;char s[10];
	while(scanf("%s",s)!=EOF){
		for(i=f=1;f&&i<41;++i)
		   for(j=-1;f&&j<2;j+=2){
				for(k=0;k<4&&check(k,i,j,s[k]);++k);
				if(k<4)continue;
				f=0;
				printf("%d %s\n",i,j==-1?"light":"heavy");
		   }		     
	}
	return 0;
}
解法二:
#include <stdio.h>
char ss[2][10]={"light","heavy"};
int main(){
	char s[5];
	int b3[4]={1,3,9,27},i,rs,f;
	while(scanf("%s",s)!=EOF){
		for(i=rs=0,f=1;i<4;++i)
		    if(s[i]!='='){
		    	if(s[i]=='>')rs-=b3[i];
		    	else rs+=b3[i];
		    	f*=-1;
			}
		rs*=f;
		f=rs>0?1:0;
		if(rs<0)rs=-rs;
		printf("%d %s\n",rs,ss[f]);
	}
	return 0;
}



G题

题面:

在这里插入图片描述

题意|分析:

十六进制字符串表示的X、Y,判断2X+10和3Y+5的大小。
很明显的大整数计算,将计算结果表示出,再比较即可。
而python有专门的十六进制库,可以秒杀。

题解:

[1]补解:

#include <iostream>
#include <vector>
using namespace std;
vector<int> mul(vector<int> &A, int b)
{
    vector<int> C;
    int t = 0;
    for (int i = 0; i < A.size() || t; i++)
        {
            if (i < A.size())
                t += A[i] * b;
            C.push_back(t % 16);
            t /= 16;
        }
    while (C.size() > 1 && C.back() == 0)
        C.pop_back();
    return C;
}

vector<int> add(vector<int> &A, vector<int> &B)
{
    vector<int> C;
    int t = 0;
    for (int i = 0; i < A.size() || i < B.size(); i++)
        {
            if (i < A.size())
                t += A[i];
            if (i < B.size())
                t += B[i];
            C.push_back(t % 16);
            t /= 16;
        }
    if (t)
        C.push_back(1);
    return C;
}
bool gt(vector<int> &A, vector<int> &B)
{
    if (A.size() != B.size())
        return A.size() > B.size();
    for (int i = A.size() - 1; i >= 0; i--)
        {
            if (A[i] != B[i])
                return A[i] > B[i];
        }
    return false;
}
int main()
{
    int t;
    cin >> t;
    while (t--)
        {
            string a;
            string b;
            cin >> a >> b;
            vector<int> A;
            for (int i = a.size() - 1; i >= 0; i--)
                {
                    if (a[i] >= '0' && a[i] <= '9')
                        A.push_back(a[i] - '0');
                    else
                        A.push_back(a[i] - 'A' + 10);
                }
            vector<int> A1 = mul(A, 2);
            vector<int> B;
            for (int i = b.size() - 1; i >= 0; i--)
                {
                    if (b[i] >= '0' && b[i] <= '9')
                        B.push_back(b[i] - '0');
                    else
                        B.push_back(b[i] - 'A' + 10);
                }
            vector<int> B1 = mul(B, 3);
            vector<int> C;
            C.push_back(5);
            vector<int> A2 = add(A1, C);
            if (gt(A2, B1))
                {
                    cout << "Yes" << endl;
                }
            else
                cout << "No" << endl;
        }
    return 0;
}

[2]官解

C++解法
#include<bits/stdc++.h>
using namespace std;
#define pb push_back
#define all(x) x.begin(),x.end()
int to(char ch){
    if(ch <= '9' && ch >= '0') return ch-'0';
    else if(ch <= 'F' && ch >= 'A') return ch-'A'+10;
    else assert(0); return 0;
}
bool f(string x, string y){
    reverse(all(x)); reverse(all(y));
    vector<int> a(x.size()), b(y.size());
    for(int i = 0; i < x.size(); ++i) a[i] = to(x[i]), a[i] *= 2;
    for(int i = 0; i < y.size(); ++i) b[i] = to(y[i]), b[i] *= 3;
    a[0] += 10; b[0] += 5;
    for(int i = 0; i < a.size(); ++i){
        int z = a[i]/16; a[i] %= 16;
        if(z){
            if(i+1 == a.size()) a.pb(0);
            a[i+1] += z;
        }
    }
    for(int i = 0; i < b.size(); ++i){
        int z = b[i]/16; b[i] %= 16;
        if(z){
            if(i+1 == b.size()) b.pb(0);
            b[i+1] += z;
        }
    }
    if(a.size() > b.size()) return true;
    else if(a.size() < b.size()) return false;
    else{
        for(int i = (int)a.size()-1; i >= 0; --i) if(a[i] != b[i]) return a[i] > b[i];
        return false;
    }
}
void sol(){
    int T; cin>>T;
    while(T--){
        string x, y;
        cin>>x>>y;
        if(f(x, y)) cout<<"Yes"<<'\n';
        else cout<<"No"<<'\n';
    }
    return;
}
int main(){
    sol();
    // int T = 20;
    // char inp[50], otp[50];
    // for(int i = 1; i <= 20; ++i){
    //     sprintf(inp, "%d.in", i);
    //     sprintf(otp, "%d.out", i);
    //     freopen(inp, "r", stdin);
    //     freopen(otp, "w", stdout);
    //     sol();
    // }
    return 0;
}
python解法
T=int(input().split()[0])
for cas in range(T):
    a,b=map(str,input().split())
    x=int(a,16)
    y=int(b,16)
    if x*2+10>y*3+5:
        print("Yes")
    else:
        print("No")




H题

题面:

在这里插入图片描述
在这里插入图片描述

题意|分析:

签到题,最基础的博弈,判断石子总数的奇偶即可

题解:

#include<iostream>
using namespace std;
int main(){
    int T;
    scanf("%d",&T);
    while(T--){
        int n;
        scanf("%d",&n);
        int sum=0;
        while(n--){
            int tmp;
            scanf("%d",&tmp);
            sum+=tmp;
        }
        if(sum&1)printf("Alice\n");
        else printf("Bob\n");
    }
    return 0;
}



I题

题面:

在这里插入图片描述

题解:

#include<iostream>

#define maxn 5003
#define inf 998244353

using namespace std;

bool now;
int n,a[maxn],dp[2][maxn];

signed main(){
	cin>>n;
	for(int i=0;i<n;i++){
		cin>>a[i];
	}
	dp[0][0]=dp[1][0]=0;
	for(int i=1;i<n;i++) dp[0][i]=dp[1][i]=-inf;
	for(int i=0;i<n;i++){
		now=!now;
		for(int j=0;j<n;j++) dp[now][j]=dp[!now][j];
		
		for(int j=0;j<n;j++){
			dp[now][j]=max(dp[now][j],dp[!now][(j-a[i]+n)%n]+1);
		}
	}
	
//	for(int i=0;i<n;i++){
//		cout<<dp[now][i]<<' ';
//	}
//	cout<<endl;
	
	for(int t=1;t<=n;t++){
		int ans=0;
		for(int i=0;i<n;i++){
			if(t*i%n==0) ans=max(ans,dp[now][i]);
		}
		cout<<ans<<' ';
	}
	cout<<endl;
	return EOF+1;
}

J题

题面

在这里插入图片描述
在这里插入图片描述

题意|分析:

在这里插入图片描述

题解:

#include<bits/stdc++.h>
#define ll long long
#define eb emplace_back
#define fi first
#define se second
using namespace std;
const int M=50009;
const int B=160;
int n,m,q,id,num;
vector<pair<int,int>>g[M];
vector<int>s[M];
int b[M];
ll ans[B<<1][M];
ll d[M];
int a[M],tid[M],dep[M],f[M<<1][23],p[M][2];
void dfs(int u,int fa){
	f[tid[u]=++id][0]=u;dep[u]=dep[fa]+1;
	for(auto o:g[u]){
		int v=o.fi,w=o.se;
		if(v!=fa){d[v]=d[u]+w;dfs(v,u);f[++id][0]=u;}
	}
}
int Min(int l,int r){return dep[l]<dep[r]?l:r;}
int lca(int x,int y){
	if(tid[x]>tid[y])swap(x,y);
	int k=log2(tid[y]-tid[x]+1);
	return Min(f[tid[x]][k],f[tid[y]-(1<<k)+1][k]);
}
ll dis(int x,int y){
	int w=lca(x,y);
	return d[x]+d[y]-d[w]-d[w];
}
void sol(int x){
	int y=b[x];
	for(int i=1;i<=m;++i){
		ans[y][i]=1ll<<60;
		if(s[i].size()>s[x].size()||(s[i].size()==s[x].size()&&i>x))continue;
		for(auto o:s[i]){
			ans[y][i]=min(ans[y][i],max({dis(o,p[i][0]),dis(o,p[i][1]),dis(o,p[x][0]),dis(o,p[x][1])}));
		}
	}
}
unordered_map<int,ll>mp[M];
int main(){
//	freopen("20.in","r",stdin);
//	freopen("1.out","w",stdout);
	scanf("%d%d",&n,&m);
	assert(n>=1&&n<=5e4&&m>=1&&m<=n);
	for(int i=1,u,v,w;i<n;++i){
		scanf("%d%d%d",&u,&v,&w);
		assert(u>=1&&u<=n&&v>=1&&v<=n);
		assert(w>=1&&w<=1e5);
		g[u].eb(v,w);
		g[v].eb(u,w);
	}
	dfs(1,0);
	for(int j=1;j<=23;++j){
		for(int i=1;i<=id-(1<<j)+1;++i){
			f[i][j]=Min(f[i][j-1],f[i+(1<<(j-1))][j-1]);
		}
	}
	for(int i=1;i<=n;++i){
		scanf("%d",&a[i]);
		assert(a[i]>=1&&a[i]<=m);
		s[a[i]].eb(i);
		p[a[i]][0]=p[a[i]][1]=i;
	}
	for(int i=1;i<=n;++i){
		if(dis(1,i)>dis(1,p[a[i]][0]))p[a[i]][0]=i;
	}
	for(int i=1;i<=n;++i){
		if(dis(p[a[i]][0],i)>dis(p[a[i]][0],p[a[i]][1]))p[a[i]][1]=i;
	}
//	for(int i=1;i<=m;++i){
//		assert(s[i].size()>0);
//		if(s[i].size()>B){
//			b[i]=++num;
//			sol(i);
//		}
//	}
	scanf("%d",&q);
	//assert(q>=1&&q<=5e4);
	for(int i=1,x,y;i<=q;++i){
		scanf("%d%d",&x,&y);
		assert(x>=1&&x<=n&&y>=1&&y<=n&&x!=y);
		if(s[x].size()<s[y].size()||(s[x].size()==s[y].size()&&x<y))swap(x,y);
		if(mp[x].count(y))printf("%lld\n",mp[x][y]);
		else {
			ll w=1ll<<60;
			for(auto o:s[y]){
				w=min(w,max({dis(o,p[y][0]),dis(o,p[y][1]),dis(o,p[x][0]),dis(o,p[x][1])}));
			}
			mp[x][y]=w;
			printf("%lld\n",w);
		}
	}
	return 0;
}

K题

题面

在这里插入图片描述
在这里插入图片描述

题解:

#include<bits/stdc++.h>
using namespace std;
const int M=2e6+9;
int n,x,y;
int a[M],b[M],f[M],s1[M],s2[M];
bool vis[M];
int main(){
//	char pt[50];
//	for(int i=30;i<=37;i++){
//		sprintf(pt,"%d.in",i);
//		freopen(pt,"r",stdin);
//		sprintf(pt,"%d.out",i);
//		freopen(pt,"w",stdout);
		scanf("%d",&n);
		for(int i=0;i<n;++i)scanf("%d",&a[i]),b[a[i]]=i,vis[i]=0;
		
		for(int i=0;i<n;++i){
			vis[a[i]]=1;
			s1[i+1]=(a[i]+n-a[i?i-1:n-1])%n;
			s2[i+1]=(b[i]+n-b[i?i-1:n-1])%n;
			s1[n+i+1]=s1[i+1];
			s2[n+i+1]=s2[i+1];
		}
		for(int i=0;i<n;++i)assert(vis[i]==1);
		for(int i=1,j=0;i<=n*2;f[++i]=++j)while(j&&s1[i]!=s1[j])j=f[j];
		x=n*2+1-f[n*2+1];
		for(int i=1,j=0;i<=n*2;f[++i]=++j)while(j&&s2[i]!=s2[j])j=f[j];
		y=n*2+1-f[n*2+1];
		bool bol=0;
		if(x==y){
			for(int i=1,j=1;i<=n*2;++i,++j){
				while(j&&s1[i]!=s2[j])j=f[j];
				if(j==x){bol=1;break;}
			}
		}
		printf("%lld\n",1ll*(x+(bol?0:y))*n);
//	}
	return 0;
}

L题

题面:

在这里插入图片描述
在这里插入图片描述

题解:BFS

[1]补解:

#include<iostream>
#include<queue>
using namespace std;
using p=pair<int,int>;
const int N=110;
char a[N][N];
bool visited[N][N];
int mx,my,tx,ty;
int n,m;
int dx[4]={0,1,0,-1};
int dy[4]={1,0,-1,0};
bool bfs(int x,int y){
    queue<p>q;
    q.push({x,y});
    visited[x][y]=true;
    while(!q.empty()){
        p tmp=q.front();
        q.pop();
        int t1=tmp.first;
        int t2=tmp.second;
        if(t1==tx&&t2==ty)return true;
        for(int i=0;i<4;i++){
            int nx=t1+dx[i];
            int ny=t2+dy[i];
            if(visited[nx][ny]||nx<1||nx>n||ny<1||ny>m||a[nx][ny]=='o')continue;
            q.push({nx,ny});
            visited[nx][ny]=true;
        }
    }
    return false;
}
int main(){
    cin>>n>>m;
    for(int i=1;i<=n;i++)scanf("%s",a[i]+1);
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            if(a[i][j]=='P'){mx=i;my=j;}
            if(a[i][j]=='X'){tx=i;ty=j;}
        }
    }
    if(bfs(mx,my))puts("Playftql");
    else puts("Playftcl");
    return 0;
}

[2]官解:

#include<bits/stdc++.h>
using namespace std;
const int maxn=105;
char mp[maxn][maxn];
struct nod {
	int r,c;
};
int dir_r[]={1,0,-1,0};
int dir_c[]={0,1,0,-1};
int n,m;
bool check(int r,int c) {return (r>=1&&r<=n&&c>=1&&c<=m)&&mp[r][c]!='o';}
bool vis[maxn][maxn];
bool bfs(int r,int c) {
	queue<nod>q;
	q.push(nod{r,c});
	while(!q.empty()) {
		nod u=q.front();
		q.pop();
		if(vis[u.r][u.c]) continue;
		if(mp[u.r][u.c]=='X') return 1;
		vis[u.r][u.c]=1;
		for(int i=0;i<4;i++) {
			int tor=dir_r[i]+u.r;
			int toc=dir_c[i]+u.c;
			if(check(tor,toc)&&!vis[tor][toc]) {
				q.push(nod{tor,toc});
			}
		}
	}
	return 0;
}
void sol() {
	cin>>n>>m;
    assert(1<=n&&n<=100&&1<=m&&m<=100);
	memset(vis,0,sizeof(vis));
	for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) cin>>mp[i][j];
    int cntp=0,cntx=0;
    for(int i=1;i<=n;i++) {
        for(int j=1;j<=m;j++) {
            if(mp[i][j]=='X') cntx++;
            else if(mp[i][j]=='P') cntp++;
            else assert(mp[i][j]=='.'||mp[i][j]=='o');
        }
    }
    assert(cntp==1&&cntx==1);
	for(int i=1;i<=n;i++) {
		for(int j=1;j<=m;j++) {
			if(mp[i][j]=='P') {
				bool ok=bfs(i,j);
				if(ok) cout<<"Playftql";
				else cout<<"Playftcl";
                return;
			}
		}
	}
}
int main() {
	sol();
	return 0;
}



后记:

1.要及时补题
2.少刷水题,跳出舒适圈。在力扣上水简单题,不去挑战,下场是很惨的。
3.ACM很有挑战性,更多地考验思维和编程素养。还是要多多加油啊
在这里插入图片描述
————本图来自2019年湖南大学新生杯

  • 7
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

0<Solving)1

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值