每一年都奔走在自己热爱里

没有人是一座孤岛,总有谁爱着你

AtCoder Beginner Contest 258

AtCoder Beginner Contest 258

B

B

题目大意是给你一个表格(nXn),每一个位置上有一个数,我们要从某一个位置出发,走n-1步,将每一步得到的数都连在一起,求出连在一起的最大值,(第一步确定方向,后面的n-2步都要和第一步方向相同)

这个题我大意了(我以为是四个方向)

n<=10,那么我们可以直接取max,一个一个找,不会超时

注意边界的处理

#include <iostream>
#include <string>
using namespace std;
#define int long long 
const int maxn=20;
string s[maxn];
int n;
int dx[9]={0,0,-1,1,-1,-1,1,1};
int dy[9]={-1,1,0,0,1,-1,-1,1};
int ans=0;
int dfs(int x,int y)
{
    for (int k=0;k<8;k++)
    {
        int res=s[x][y]-'0';
        for (int i=2;i<=n;i++)
        {
            int ttx=x+dx[k];
            int tty=y+dy[k];
            if (ttx>n)
            {
                ttx=1;
            }
            if (ttx==0)
            {
                ttx=n;
            }
            if (tty>n)
            {
                tty=1;
            }
            if (tty==0)
            {
                tty=n;
            }
            res=res*10+(s[ttx][tty]-'0');
            x=ttx,y=tty;
        }
        ans=max(ans,res);
    }
    return ans;
}
signed  main ()
{
    cin>>n;
    int posx=0,posy=0;
    for (int i=1;i<=n;i++)
    {
        cin>>s[i];
        s[i]=" "+s[i];
    }
    for (int i=1;i<=n;i++)
    {
        for (int j=1;j<=n;j++)
        {
            ans=min(ans,dfs(i,j));
        }
    }
    cout<<ans<<'\n';
    system ("pause");
    return 0;
}

C

C

题目大意是给你一个长度为n的字符串s,下面有n个操作,有两种操作类型,输入一个op,一个x

op=1,那么就把后面的x个字符移到前面来

op=2,那么我们需要输出第x个字符

这个用直接模拟的话会超时

我们可以不改变s,只是改变第一个字符的位置pos

如果要把x个字符移动到前面,那么第一个字符的位置就要加上x(pos+=x)

对于输出x个字符

我们可以直接输出第(x-pos+n)%n个字符(假如x=pos,那么我们输出的就是第一个,x=pos+1,那么就是第2个),注意字符的第1个是s[0],所以我们需要先减1

#include <iostream>
#include <string>
using namespace std;
string s;
int n,m;
int main ()
{
    cin>>n>>m;
    cin>>s;
    int st=0;
    while (m--)
    {
        int op,x;
        cin>>op>>x;
        if (op==1)
        {
            st+=x;
            st%=n;
        }
        else 
        {
            x--;
            int pos=(x-st+n)%n;
            cout<<s[pos]<<'\n';
        }
    }
    system ("pause");
    return 0;
}

D

D

这个给我们一个x,还有n个a,b,我们必须从1开始,对于第一次使用,必须用到a,b(价值为1),下一次可以找下一个a,b,或者是还是使用这一个,这一次不是使用的第一次,那么我们只需要使用b(价值为1),我们需要知道要价值达到x的最sum

我这个差一点了,就是没有考虑到x小于n的情况(下次一定要注意)

#include <iostream>
using namespace std;
const int maxn=5e5+10;
#define int long long 
int f[maxn];
int n,x,a[maxn],b[maxn];
signed main ()
{
    cin>>n>>x;
    for (int i=1;i<=n;i++)
    {
        cin>>a[i]>>b[i];
    }
    int sum=0;
    int ans=0;
    for (int i=1;i<=n&&i<=x;i++)
    {
        sum+=a[i]+b[i];
        f[i]=sum+(x-i)*b[i];//如果没有考虑到x小于n,那么会出现负数
        if (i==1)
        {
            ans=f[i];
        }
        else 
        {
            ans=min(ans,f[i]);
        }
    }
   // ans++;
    cout<<ans<<'\n';
    system ("pause");
    return 0;
}

E

E

这个题大意是从1到n,然后到1,然后到n这样一个循环,我们每一次都会选择若干个数,(按顺序),如果大于x(题目给出),那么我们就需要另外一个新的集合了,后面有q次询问,问第几个集合里面有几个数

这个我们可以猜测会出现循环(其实我还是有点不太明白为什么不会超时,哎,)

我们只要找出这一个集合以这个位置为第一个放入的数,后面还出现了以这一个位置为第一个放入的数,那么此时就是出现了循环,后面的就不需要找了

对于我们要找从i到j这一段刚好是大于等于x,这里用了前缀和和二分

具体看代码

#include <iostream>
#include <map>
#include <vector>
#include <algorithm>
using namespace std;
#define int long long 
const int maxn=2e5+10;
int n,w[maxn],x,q;
int vis[maxn],sum[maxn];
int cnt,s,t;
int len;
signed main ()
{
    vector<int>f;
    f.push_back(0);
    cin>>n>>q>>x;
    for (int i=1;i<=n;i++)
    {
        cin>>w[i];
        sum[i]=sum[i-1]+w[i];
    }
    int now=1;
    while (!vis[now])
    {
        vis[now]=++cnt;
        if (sum[n]-sum[now-1]>=x)
        {
            int pos;//下一个
            pos=lower_bound(sum+1,sum+1+n,sum[now-1]+x)-sum;//找到的sum[pos]-sum[now-1]>=x
            f.push_back(pos-now+1);//这一次放入了几个数
            //cout<<pos-now+1<<' ';
            now=pos+1;//下一个
            if (now==n+1) now=1;
        }
        else //这个情况是还不够,还需要1到pos的数,若干个n个数,还要pos个数
        {
            int tmp=x-(sum[n]-sum[now-1]);
            int res=n-now+1+(tmp/sum[n])*n;
            tmp%=sum[n];
            int pos=lower_bound(sum+1,sum+1+n,tmp)-sum;
            res+=pos;
            f.push_back(res);
            now=pos+1;
            if (now==n+1) now=1;
        }
        if (vis[now])//这个时候就出现了循环
        {
            s=vis[now],t=cnt;//s是开始进入循环的点,前面的不是循环里面的
            len=t-s+1;//len为周期
            break;
        }
    }
    //cout<<'\n';
    while (q--)
    {
        int x;
        cin>>x;
        if (x<=cnt)//如果有答案,就直接输出
        {
            cout<<f[x]<<'\n';
        }
        else //否则利用循环
        {
            int p=x-cnt;//多出的长度
            p%=len;
            if (p==0) p=len;
            cout<<f[s-1+p]<<'\n';//p只是循环里的第几个,而f里是s-1后面才出现的循环
        }
    }
    system ("pause");
    return 0;
}

F

F

这个题目我理解了好久

就是有一个sx,sy,ex,ey,我们要从sx,sy到ex,ey,对于每一步,(可以有四个方向,上下左右),而对于x或者y是b的倍数的时候走这一段需要1s,其他的我们需要ks

我们就是要找最少的时间

有一种最直接的方式,

直接走,不走高速dis=(abs(sx-ex)+abs(sy-ey))*k

还有,就是先到高速,(起点终点都到高速),到哪一个高速呢,我们有四个方向,到上面的高速,下面的高速,左面的高速,右面的高速

对于两个点的高速都是同一个方向的(都是横向,竖向的)

我们要这几种走法

对于是不同方向的

我们直接这样走

对于不同的走法,我们取Min

#include <iostream>
#include <string>
#include <vector>
#include <cmath>
using namespace std;
#define int long long 
#define min4(x,y,z,q) min(x,min(y,min(z,q)))
const int maxn=2e5+10;
int b,k,sx,sy,ex,ey;
vector<pair<int,int>> fun(int x,int y)//四个方向最近的高速
{
    vector<pair<int,int>>a;
    a.push_back({x,y+b-(y%b)});
    a.push_back({x,y-(y%b)});
    a.push_back({x+b-(x%b),y});
    a.push_back({x-(x%b),y});
    return a;
}
int cal(int x,int y,int xx,int yy)
{
    int res=2e18;
    bool flag=false;
    if(x/b==xx/b&&y%b==0&&yy%b==0)//y都是高速
    {
        flag=true;
        int tmp=abs(y-yy)*k+abs(x-xx);
        res=min(res,tmp);
        tmp=abs(y-yy)+ (b-x%b+b-xx%b);
        res=min(res,tmp);
        tmp=tmp=abs(y-yy)+ (x%b+xx%b);
        res=min(res,tmp);
    }
   if(y/b==yy/b&&x%b==0&&xx%b==0)//x都是高速
    {
        flag=true;
        int tmp=abs(x-xx)*k+abs(y-yy);
        res=min(res,tmp);
        tmp=abs(x-xx)+ (b-y%b+b-yy%b);
        res=min(res,tmp);
        tmp=tmp=abs(x-xx)+ (y%b+yy%b);
        res=min(res,tmp);
    }
    if (!flag)//一个是x,一个是y
    {
        int tmp=abs(x-xx)+abs(y-yy);
        res=min(res,tmp);
    }
    return res;
}

void solve()
{
    cin>>b>>k>>sx>>sy>>ex>>ey;
    vector<pair<int,int>>s=fun(sx,sy);
    vector<pair<int,int>>g=fun(ex,ey);
   int ans=(abs(sx-ex)+abs(sy-ey))*k;
    for (int i=0;i<4;i++)
    {
        int tx=s[i].first;
        int ty=s[i].second;
        for (int j=0;j<4;j++)
        {
            int ttx=g[j].first;
            int tty=g[j].second;
            int tmp=(abs(tx-sx)+abs(ty-sy)+abs(ttx-ex)+abs(tty-ey))*k+cal(tx,ty,ttx,tty);
            ans=min(ans,tmp);
        }
    }
    cout<<ans<<'\n';
    return ;
}
signed main ()
{
    int t;
    cin>>t;
    while (t--)
    {
        //cout<<t<<"next\n";
        solve();
    }
    system ("pause");
    return 0;
}

G

G

这个题是还是一个表格,ai,j代表i,j是否连通,(1代表连通,0代表不连通)

我是要找出i,j,k都互相连通的数量

这个我试过一个一个找,不过超时了

但是这个如果用bitset来写真的很好,因为bitset可以直接看成二进制进行&运算,如果两个都是1,那么说明那一个既可以到达i,又可以到达j(注意不要把重复的加进去,和本身),然后我们还可以直接求出1的数量,真是太好用了

#include <iostream>
#include <bitset>
#include <vector>
#include <string>
using namespace std;
#define int long long 
const int maxn=3e3+10;
int ans;
bitset<3000>g[maxn];
string s;
int n;
signed main ()
{
    cin>>n;
    for (int i=1;i<=n;i++)
    {
        string s;
        cin>>s;
        s=" "+s;
        for (int j=i+1;j<=n;j++)//我们直接存后面的,前面的不保存,不会重复
        {
            if (s[j]=='1')
            {
                g[i][j]=1;
            }
        }
    }
    for (int i=1;i<=n;i++)
    {
        for (int j=i+1;j<=n;j++)
        {
            if (g[i][j])
            {
                ans+=(g[i]&g[j]).count();
            }
        }
    }
    cout<<ans<<'\n';
    system ("pause");
    return 0;
}
posted @   righting  阅读(17)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示