兰州大学第一届『飞马杯』程序设计竞赛

这篇博客探讨了算法竞赛中的新比赛机制,强调了解题思路和前缀和在优化罚时计算中的应用。作者通过实例展示了如何使用两个前缀和来找到最短总罚时,并分享了在处理大规模数据时使用快读技巧的重要性。此外,还介绍了生命游戏的暴力解决方案和寻找字符串子串的两种有效方法。
摘要由CSDN通过智能技术生成

比赛新机制

题意:一个环,任取一个起点和一个方向(正方向 Or 逆方向),求总罚时最短

思路:罚时是解每道题目的时间的和,显然要用前缀和来解答,求一次前缀和,即求出每个题的罚时

复盘:两个方向,想到了要用两个前缀和来维护

​ 最初的想法,想对前缀和再求取一次前缀和(见代码(43~51),想通过新的前缀和直接得到从每个点出发的总罚时————这样是错的(写题要有条理

最后饶了半天,才发现要从第一次前缀和入手,然后就推出来了两个计算公式

坑点:要用快读,数据 (10^5) * (10^5) …

Ac Code:

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

const int N=1000005;
int a[N], s1[N], s2[N];
int minn(int a,int b)
{
    if(a<b) return a;
    return b;
}
inline int read()
{
	int X=0; bool flag=1; char ch=getchar();
	while(ch<'0'||ch>'9') {if(ch=='-') flag=0; ch=getchar();}
	while(ch>='0'&&ch<='9') {X=(X<<1)+(X<<3)+ch-'0'; ch=getchar();}
	if(flag) return X;
	return ~(X-1);
}
signed main()
{
    int t,n;
    scanf("%lld",&t);
    while(t--)
    {
        //memset(s1,0,sizeof s1);
        //memset(s2,0,sizeof s2);
        n = read();
        int sum1=0, sum2=0;
        for(int i=1;i<=n;i++)
        {
            a[i] = read();
            //a[i+n] = a[i];
            s1[i] = s1[i-1]+a[i];
            sum1 += s1[i];
        }
        s2[n+1]=0;
        for(int i=n;i>=1;i--)
        {
            s2[i] = s2[i+1]+a[i];
            sum2 += s2[i];
        }
        /*
        for(int i=1;i<=n;i++)
        {
            s1[i] += s1[i-1];
        }
        for(int i=n;i>=1;i--)
        {
            s2[i] += s2[i+1];
        }*/
        int ans = 1e17;
        for(int i=1;i<=n;i++)
        {
            int cnt=n-i+1;
            ans=min(ans,sum1-cnt*s1[i-1]+(n-cnt)*(s1[n]-s1[i-1]));
            ans=min(ans,sum2-i*s2[i+1]+(n-i)*(s2[1]-s2[i+1]));
        }
        printf("%lld\n",ans);
        /*cout<<sum1<<' '<<sum2<<' '<<ans<<endl;
        for(int i=1;i<=n;i++) cout<<s1[i]<<' ';cout<<endl;
        for(int i=1;i<=n;i++) cout<<s2[i]<<' ';cout<<endl;
*/
    }

    return 0;
}


生命的游戏

​ 暴力~

Ac Code:

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

const int N=1005;
int minn(int a,int b)
{
    if(a<b) return a;
    return b;
}

int a[N][N], b[N][N], t[N][N];
int dx[10]={0,0,1,1,1,-1,-1,-1};
int dy[10]={1,-1,0,1,-1,0,1,-1};
void change(int n)
{
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=n;j++)
        {
            t[i][j] = b[i][j];
            int cnt=0;
            for(int p=0;p<8;p++)
            {
                int x=(i+dx[p]+n-1)%n+1, y=(j+dy[p]+n-1)%n+1;
                if(b[x][y]) cnt++;
            }
            if(b[i][j] && (cnt>3 || cnt<2)) t[i][j]=0;
            if(!b[i][j] && cnt==3) t[i][j]=1;
        }
    }
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=n;j++) b[i][j]=t[i][j];
    }
}

signed main()
{
    int t,n, k;
    scanf("%lld",&t);
    while(t--)
    {
        //memset(s1,0,sizeof s1);
        //memset(s2,0,sizeof s2);
        scanf("%lld%lld",&n,&k);
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=n;j++)
            {
                scanf("%lld",&a[i][j]);
                b[i][j]=a[i][j];
            }
        }
        int flag=1;
        for(int p=1;p<=k;p++)
        {
            int fg=1;
            change(n);
            for(int i=1;i<=n && fg;i++)
            {
                for(int j=1;j<=n && fg;j++)
                {
                    if(b[i][j]!=a[i][j]) fg = 0;
                }
            }
            if(fg)
            {
                cout<<"YES"<<endl<<p<<endl;
                flag=0;
                break ;
            }
        }
        if(flag) cout<<"NO"<<endl;
    }

    return 0;
}


飞马分隔符

注意子串"FeiMa"是非连续的!!

Ac Code:(solution one)

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

string str = "FeiMa";
int main()
{
    int n, t;
    cin>>t;
    while(t--)
    {
        cin>>n;
        string s;
        cin>>s;
        int fg=1, ans=0, p=0;
        while(fg)
        {
            for(int i=0; i<5 && fg; i++)
            {
                p = s.find(str[i], p);
                if(p==-1) fg = 0;
            }
            if(fg) ans++;
        }
        cout<<ans<<endl;
    }

    return 0;
}

Ac Code:(solution two)

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

string str = "FeiMa";
int main()
{
    int n, t;
    cin>>t;
    while(t--)
    {
        cin>>n;
        string s;
        cin>>s;
        int fg=0, ans=0;
        for(int i=0; i<n; i++)
        {
            if(fg==0 && s[i]==str[0]) fg++;
            if(fg==1 && s[i]==str[2]) fg++;
            if(fg==2 && s[i]==str[3]) fg++;
            if(fg==3 && s[i]==str[4]){ fg = 0; ans++; }
        }
        cout<<ans<<endl;
    }

    return 0;
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

yezzz.

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

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

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

打赏作者

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

抵扣说明:

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

余额充值