黑龙江大学程序设计竞赛(重现赛)

虽然我们是打的团队赛,但我并没有做出什么贡献,貌似本人一个都没过,全程划水。全靠摊了两个好队友才A了七个出来。但赛后发现其实这些题我都是写得出的(除了F那个超时我真的没办法之外)。题目都挺简单的,但我想复杂了

Problem A Find the Nth Character

https://ac.nowcoder.com/acm/contest/877/A

题意:一个如题的字符串,求字符串中的第n个字符。

方法一:直接打表模拟。

#include<iostream>
#include<cstdio>
using namespace std;
char aa[30];
char ans[100100];
void init()
{
    for(int i=1;i<=26;i++)
    {
        aa[i]=i+'a'-1;
    }
    int k=1,l;
    for(int i=1;i<200;i++)
    {
        for(int j=1;j<=i;j++)
        {
            int l=j%26;
            if(l==0) l=26;
            ans[k++]=aa[l];
        }
    }
}
int main()
{
    init();
    int k,n;
    cin>>k;
    while(k--)
    {
        cin>>n;
        cout<<ans[n]<<endl;
    }
    return 0;
}

方法二:请看代码理解

c++版本:

#include <bits/stdc++.h>
using namespace std;
int main()
{
    int t,n;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d",&n);
        int s=1;
        while(n>s)
        {
            n-=s;
            s++;
        }
        n=(n-1)%26;
        printf("%c\n",n+'a');
    }
}

python版本:

input();
while True:
    try:
        x=int(input());
        s=1;
        while x>s:
            x=x-s;
            s=s+1;
        x=(x-1)%26;
        print(chr(x+ord('a')));
    except:
        break;

Problem B Help Me

https://ac.nowcoder.com/acm/contest/877/B

题意:

方法:将完全平方公式拆开然后分类即可发现,a[i]的平方各有n-1个,对于-2*a[i]*a[j]可用前缀和或后缀和减少时间复杂度。用前缀和比后缀和代码更简单。

c++:(后缀和版本,比赛时没想到前缀和,后来也没改了)代码可能很傻,将就下吧

#include <bits/stdc++.h>
using namespace std;
long long a[50005];
long long b[50005];
int main()
{
    scanf("%*d");
    int n;
    while(scanf("%d", &n)==1)
    {
        long long sum=0;
        memset(b,0,sizeof(b));
        int d=(n-1);
        for(int i=1;i<=n;i++)
        {
            scanf("%lld", &a[i]);
            b[i]=1ll*(b[i-1]+a[i]);
            sum+=d*(a[i]*a[i])*1ll;
        }
        for(int i=n-1;i>=1;i--)
        {
            long long x=(b[n]-b[i])*1ll;
            x*=a[i]*1ll;
            sum-=x*1ll;
            sum-=x*1ll;
        }
        printf("%lld\n",sum);
    }
}

python版本:

input();
while True:
    try:
        n=int(input());
        a=input().split();
        sum=int(0);
        ans=int(0);
        d=int(n)-1;
        for i in range(n):
            sum += int(a[i]);
        for i in range(n):
            ans+=int(a[i])*int(a[i])*d-int(a[i])*(sum-int(a[i]));
        print(ans);
    except:
        break;

Problem C Challenge IQ

https://ac.nowcoder.com/acm/contest/877/C

将n个数通过一定顺序首尾连接形成一个圆环,使得相邻元素互质的对数尽可能多,请输出最大的对数。

方法:对任意自然数,n与n+1互质

c++版本:

#include<iostream>
#include<cstdio>
using namespace std;
int main()
{
    int t,n;
    cin>>t;
    while(t--)
    {
        cin>>n;
        cout<<n<<endl;
    }
    return 0;
}

python:

input();
while True:
    try:
        a=input();
        print(a);
    except:
        break;

Problem D Schedules

https://ac.nowcoder.com/acm/contest/877/D

题意:有n个任务,有固定的开始和结束时间,同一个机器不能同时进行两个任务,求至少需要几台机器

方法:建立一根时间轴,如果某一时刻有机器启动,将轴上此时的值加一,表示有一台机器启动。若某时刻有机器停止运行则减一。然后从头到尾遍历一遍求前缀和,则最大的前缀和便是所需要的最少机器数。

c++版本一:

#include <bits/stdc++.h>
using namespace std;
const int maxn=1e5+5;
int a[maxn];
int main()
{
    int n;
    scanf("%d",&n);
    int m=-1;
    for(int i=0;i<n;i++)
    {
        int x,y;
        scanf("%d %d",&x,&y);
        a[x]++;
        a[y]--;
        m=max(m,y);
    }
    int sum=0,ans=-0x3f3f3f3f;
    for(int i=0;i<=m;i++)
    {
        sum+=a[i];
        ans=max(ans,sum);
    }
    printf("%d\n",ans);
}

c++版本二:(或许这个更容易理解一点?)

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+5;
int n,sum,ans,m,x,y,t,s,q[maxn],w[maxn];//q数组记录的是启动的机器,w是停止的
int main()
{
	scanf("%d",&n);
	for(int i=1; i<=n; i++)
	{
		scanf("%d %d",&x,&y);
		q[x]++;
		w[y]++;
		m=max(m,y);
	}
	for(int i=1; i<=m; i++)
	{
		if(w[i]!=0)
		{
			s-=w[i];
			t+=w[i];
		}
		if(q[i]!=0)
		{
			if(t-q[i]>=0)
			{
				t-=q[i];
				s+=q[i];
			}
			else
			{
				t=0;
				s+=q[i];
			}
		}
	}
	cout<<t<<endl;
	return 0;
}

python版本:

n=int(input());
maxn=int(100005);
a=[];
for i in range(maxn):
    a.append(0);
sum=int(0);
ans=int(-0x3f3f3f3f);
for i in range(n):
    x,y=map(int,input().split());
    a[x]+=1;
    a[y]-=1;
for i in range(maxn):
    sum+=a[i];
    ans=max(ans,sum);
print(ans);

Problem E Pig-Palindromic

https://ac.nowcoder.com/acm/contest/877/E

题意:求一个长度为偶数,而且对称位置分别为大写小写字母或者小写大写字母的子字符串的长度

方法:枚举相邻两点,以此为中心向两边扩散

c++版本:

#include<iostream>
#include<algorithm>
using namespace std;
int main()
{
    string a;
    while(cin>>a)
    {
        int cnt;int maxn=-9999999;
    for(int i=0;i<a.size();i++)
    {
        cnt=0;
        for(int k=i,w=i+1;k>=0&&w<a.size();)
        {
            if(a[k]+32==a[w]||a[k]-32==a[w])
            {
                cnt+=2;k--;w++;
            }
            else
                break;
        }  
        maxn=max(maxn,cnt);
    }
    cout<<maxn<<endl;
    }
}

python版本:

s=input();
cnt=int(0);
ans=int(-0x3f3f3f);
for i in range(len(s)):
    x=int(i);
    y=int(i+1);
    cnt=int(0);
    while x>=0 and y<len(s):
        if ord(s[y])-ord(s[x])==32 or ord(s[x])-ord(s[y])==32:
            x-=1;
            y+=1;
            cnt+=2;
        else:
            break;
    ans=max(ans,cnt);
print(ans);

Problem F GCD Problem

https://ac.nowcoder.com/acm/contest/877/F

题解:给定n个数,有两种操作,操作一:查询 l 到 r区间的最大公约数。操作二:将 l 到 r区间的每个数开平方根并向下取整。

方法:线段树,节点记录所在区间的最大公约数。

c++版本:

#include <bits/stdc++.h>
using namespace std;
const int maxn=3e5+5;
long long a[maxn<<2];
struct node
{
    long long num;
};
node no[maxn<<2];
void bulid(int l,int r,int loc)
{
    if(l==r)
    {
    	scanf("%lld",&a[loc]);
        no[loc].num=a[loc];
        return;
    }
    int mid=(l+r)>>1;
    bulid(l,mid,loc<<1);
    bulid(mid+1,r,loc<<1|1);
    a[loc]=a[loc<<1]+a[loc<<1|1];
    no[loc].num=__gcd(no[loc<<1].num,no[loc<<1|1].num);
}
long long query(int l,int r,int loc,int x,int y)
{
    if(l>=x && r<=y)return no[loc].num;
    if(l>y || r<x)return 0;
    int mid=(l+r)>>1;
	long long ans=0;
	if(x<=mid)ans=query(l,mid,loc<<1,x,y);
	if(y>mid)ans=__gcd(ans,query(mid+1,r,loc<<1|1,x,y));
	return ans;
	if(x>mid)return query(mid+1,r,loc<<1|1,x,y);
	else if(y<mid)return query(l,mid,loc<<1,x,y);
	else return __gcd(query(l,mid,loc<<1,x,y),query(mid+1,r,loc<<1|1,x,y));
}
void update(int l,int r,int loc,int x,int y)
{
    if(l>y || r<x)return;
	if(a[loc]==r-l+1)return;//此时区间内的值全为1,可以不进行开根号操作。不加会超时
    if(l==r)
    {
    	a[loc]=sqrt(a[loc]);
    	no[loc].num=a[loc];
//        no[loc].num=sqrt(no[loc].num);
        return;
    }
    int mid=(l+r)>>1;
    if(x<=mid)update(l,mid,loc<<1,x,y);
    if(y>mid)update(mid+1,r,loc<<1|1,x,y);
    a[loc]=a[loc<<1]+a[loc<<1|1];
    no[loc].num=__gcd(no[loc<<1].num,no[loc<<1|1].num);
}
int main()
{
    int n;
    scanf("%d",&n);

    bulid(1,n,1);
    int m;
    scanf("%d",&m);
    for(int i=0;i<m;i++)
    {
        int a,c,b;
        scanf("%d %d %d",&a,&b,&c);
        if(a==1)
        {
            printf("%lld\n",query(1,n,1,b,c));
        }
        else
        {
            update(1,n,1,b,c);
        }
    }
}

Problem G Bash Game

https://ac.nowcoder.com/acm/contest/877/G

题意:一件物品价值p元,两人轮流叫价,每次加价为1到M元,谁先出到p谁输。问最后谁会赢。

方法:巴什博奕的改版。当(n-1)%(m+1)!=0时Alice能赢.。

参考文章:博弈论

c++版本:

#include<iostream>
#include<cstdio>
#include<cmath>
using namespace std;
int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        int a,b;
        cin>>a>>b;
         
        if(b==1) {
            if(a&1) printf("Bob\n");
            else printf("Alice\n");
            continue;
        }
        if(b==2) {
            if(a%3==1) printf("Bob\n");
            else printf("Alice\n");
            continue;
        }
        if(a%(b+1)==1) printf("Bob\n");
        else printf("Alice\n");
    }
    return 0;
}

python版本:

input();
while True:
    try:
        x,y=map(int,input().split());
        #x,y=input().split(" ");
        #x=int(x);
        #y=int(y);
        x-=1;
        y+=1;
        #print("x=",x,"y=",y);
        if x%y != 0 :
            print("Alice");
        else:
            print("Bob");
    except:
        break;

Problem H Pass CET 6

https://ac.nowcoder.com/acm/contest/877/H

题意:有一个单词矩阵,一天只能背某一行或某一列的单词,求每个单词最后一次被记的时间

方法:标记某一行和某一列最后被记的时间。比较行列的最大值即该单词最后被记的时间。

c++版本:

#include <bits/stdc++.h>
using namespace std;
const int maxn=1e5+5;
int a[maxn],b[maxn];
int main()
{
    int n,m,t;
    scanf("%d %d %d",&n,&m,&t);
    for(int i=1;i<=t;i++)
    {
        int x,y;
        scanf("%d %d",&x,&y);
        if(x==1)a[y]=i;
        else b[y]=i;
    }
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=m;j++)
        {
            if(a[i]>b[j])printf("%d ",a[i]);
            else printf("%d ",b[j]);
        }
        printf("\n");
    }
}

python版本:(此代码只能过一半的测试数据,但我已经找不出问题了。还希望能有大佬指教)

maxn=int(100005);
line=[0 for x in range(0,maxn)];
column=[0 for x in range(0,maxn)];
n,m,t=map(int,input().split());
for i in range(1,t+1):
    id,num=map(int,input().split());
    if id==1:
        line[num]=i;
    else:
        column[num]=i;
for i in range(1,n+1):
    for j in range(1,m+1):
        if(line[i]>column[j]):
            print(str(line[i])+" ",end="");
        else:
            print(str(column[j])+" ",end="");
    print('');

Problem I Center Street

https://ac.nowcoder.com/acm/contest/877/I

题意:有N个仓买,如果两个仓买A,B满足A是B的倍数,则A,B之间可以通一条路。如果仓买A,B之间通路,则过路费为元。求1号仓买到其他仓买的最小花费。

方法:我也不知道这到底算贪心还是dp,虽然同学们都说这是dp。

c++版本:

#include<bits/stdc++.h>
using namespace std;
const int maxn=5e5+5;
long long dp[maxn];
const int inf=0x3f3f3f3f;
int main()
{
    memset(dp,inf,sizeof(dp));
    dp[0]=0;dp[1]=0;
    int n;
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    {
        for(int j=i+i;j<=n;j+=i)
        {
            dp[j]=min(dp[j],1ll*(j-i)*(j-i)+dp[i]);
        }
    }
    for(int i=1;i<=n;i++)
    {
        printf("%lld ",dp[i]);
    }
}

Problem J Special Distance

https://ac.nowcoder.com/acm/contest/877/J

题意:求最大值。

方法:去掉绝对值,再将含 i 的放再一块。只要保证 i大于 j,则原式子的前半部分一定是正数,只要判断后面部分即可。

c++版本:

#include <bits/stdc++.h>
using namespace std;
const long long inf=1e18;
int main()
{
    scanf("%*d");
    int n;
    while(scanf("%d",&n)==1)
    {
        long long a=-inf,b=-inf,c=inf,d=inf,x;
        for(int i=1;i<=n;i++)
        {
            scanf("%lld",&x);
            a=max(a,1ll*i*i+x*x);
            b=max(b,1ll*i*i-x*x);
            c=min(c,1ll*i*i+x*x);
            d=min(d,1ll*i*i-x*x);
        }
        printf("%lld\n",max(a-c,b-d));
    }
}

python版本:

input();
inf=0x7fffffffffffffff;
while True:
    try:
        a=-inf;b=-inf;c=inf;d=inf;
        n=int(input());
        s=input().split();
        for i in range(len(s)):
            u=(i+1)*(i+1);
            v=int(s[i])*int(s[i]);
            a=max(a,u+v);
            b=max(b,u-v);
            c=min(c,u+v);
            d=min(d,u-v);
        #print(a,b,c,d);
        print(max(a-c,b-d));
    except:
        break;

Problem K Maximum Sum of Digits

https://ac.nowcoder.com/acm/contest/877/K

题意:将一个数分成两个数的和,要求两个数每一位的数字加起来最大。

方法:因为要求每个数字的和最大,所以将其中一个数字拆出最多的9的即可。

c++版本:

#include <bits/stdc++.h>
using namespace std;
long long count(long long x)
{
    long long ans=0;
    while(x)
    {
        ans+=(x%10);
        x/=10;
    }
    return ans;
}
int main()
{
    scanf("%*d");
    long long n;
    while(scanf("%lld",&n)==1)
    {
        long long d=0;
        while(d*10+9 < n)
        {
            d=d*10+9;
        }
        printf("%d\n",count(d)+count(n-d));
    }
}

python版本:(可能有点难理解,建议手动模拟一遍)

input();
while True:
    try:
        n=int(input());
        s=0
        while n>8:
            s+=(9+(n-9)%10)
            n=int((n-9)/10)
        print(int(s+n))
    except:
        break;

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值