2019徐州网络赛 (The Preliminary Contest for ICPC Asia Xuzhou 2019)(总结+题解)

今天这场网络赛就比较舒服,(虽然一开始榜有点歪,但是基本上能做的题都做了)能A的题也不少,除了签到题,还有不少模板题,原题。最后还有一个贪心的题没有想出来,。做那么多题,也是真的有点累,(虽然套了几个板子,)

 

------------------------------------------(部分)题解------------------------------------------------

https://www.jisuanke.com/contest/3005?view=challenges

A. Who is better?

思路:看懂题意就很简单。怪物的数量用扩展中国剩余定理求出来,然后判输赢是斐波那契博弈。就两块的拼合。很简单。

但是一开始网上找的扩展中国剩余定理的板子,竟然WA了好多。最后发现竟然是,扩展中国剩余定理的板子问题,换个板子就A了。

代码:

#include<bits/stdc++.h>
typedef long long ll;
#define inf 0x3f3f3f3f3f3f3f3fLL
#define maxn 20
using namespace std;
int n;
ll M[100005],A[100005];

void ex_gcd(ll a,ll b,ll &d,ll&x,ll&y)
{
    if(!b)
    {
        d=a;
        x=1;
        y=0;
    }else{
        ex_gcd(b,a%b,d,y,x);
        y-=x*(a/b);
    }
}
ll gcd(ll a,ll b)
{
    return b==0?a:gcd(b,a%b);
}
ll CRT()
{
    ll dm,i,a,b,x,y,d;
    ll c,c1,c2;
    a=M[0];
    c1=A[0];
    for(i=1;i<n;i++)
    {
        b=M[i];
        c2=A[i];
        ex_gcd(a,b,d,x,y);
        c=c2-c1;
        if(c%d)
            return -1;
        dm=b/d;
        x=((x*(c/d))%dm+dm)%dm;
        c1=a*x+c1;
        a=a*dm;
    }
    if(c1==0)
    {
        c1=1;
        for(i=0;i<n;i++)
            c1=c1*M[i]/gcd(c1,M[i]);
    }
    return c1;
}
ll nn,a,b,c;
int main()
{
    scanf("%d",&n);
    for(int i=0;i<n;++i)
    {
        scanf("%lld%lld",&M[i],&A[i]);
    }
    nn=CRT();
    if(nn==-1) {printf("Tankernb!\n");return 0;}
    a=0;b=1;
    int ans=0;
    for(int i=1;a+b<=1e16;i++)
    {
        if(a+b==nn) {ans=1;break;}
        c=b;
        b=a+b;
        a=c;
    }
    if(ans==1) printf("Lbnb!\n");
    else printf("Zgxnb!\n");
    return 0;
}

B. so easy

思路:正解似乎是哈希+并查集思想,但是我用的map,竟然A了,然而后来发现,应该是T的..又交了几次源代码,确实卡了map的排序时间,用unordered_map就能A.这个题能A的那么快,也是人品爆棚!

代码:

#include<bits/stdc++.h>
#define ll long long
#define inf 0x3f3f3f3f3f3f3f3fLL
#define maxn 100500
using namespace std;
int n,q,z,x;
map<int,int>ma;
map<int,int>maa;
int fin(int k)
{
    if(k==-1) return -1;
    if(ma[k]==0) return k;
    else return ma[k]=fin(ma[k]);
}
int main()
{
    scanf("%d%d",&n,&q);
    ma[n]=-1;
    while(q--)
    {
        scanf("%d%d",&z,&x);
        if(z==1) {
           ma[x]=x+1;
        }
        else if(z==2)
        {
            printf("%d\n",fin(x));
        }
    }
}

C. Buy Watermelon

思路:水题,判奇偶,特判2就行.

代码:

#include<bits/stdc++.h>
#define ll long long
#define inf 0x3f3f3f3f
#define rep(i,a,b) for(register int i=(a);i<=(b);i++)
#define dep(i,a,b) for(register int i=(a);i>=(b);i--)
using namespace std;
const int maxn=2e5+5;
//const double pi=acos(-1.0);
//const double eps=1e-9;
//const ll mo=1e9+7;
int n,m,k;
int a[maxn],c[maxn];
int ans,tmp,cnt;
int flag;
char s[maxn];
bool ok[maxn];
int main()
{
    int T,cas=1;
    //scanf("%d",&T);
    while(scanf("%d",&n)!=EOF)
    {
        if(n&1) puts("NO");
        else
        {
            if(n>=4) puts("YES");
            else puts("NO");
        }
    }
    return 0;
}

D. Carneginon

思路:kmp找字串,模板,找找关系判判就完了.

代码:

#include<bits/stdc++.h>
#define ll long long
#define inf 0x3f3f3f3f3f3f3f3fLL
#define maxn 100500
using namespace std;
void getnext(char *ch,int *next)
{
    int x=strlen(ch);
    next[0]=0;
    for(int i=1,p=0;i<x;i++)
    {
        while(p>0&&ch[i]!=ch[p])
        {
            p=next[p-1];
        }
        if(ch[p]==ch[i]) p++;
        next[i]=p;
    }
}
int kmp(char *ch,char *chh,int *next)///查询ch内是否含有chh字串
{
    int n=strlen(ch),m=strlen(chh),j=0,i=0;
    while(i<n&&j<m)
    {
        if(ch[i]==chh[j])
        {
            i++;j++;
        }
        else
        {
            if(j==0) i++;
            else j=next[j-1];
        }
    }
    if(j==m) return 1;
    else
    return 0;
}

char t[maxn];
int q,a[maxn],b[maxn],n,m;
char s[maxn];
int main()
{
    scanf("%s",t);
    getnext(t,a);
    n=strlen(t);
    scanf("%d",&q);
    while(q--)
    {
        scanf("%s",s);
        m=strlen(s);
        if(n>m)
        {
            getnext(s,b);
            if(kmp(t,s,b)) {printf("my child!\n");}
            else {printf("oh, child!\n");}
        }
        else if(n==m)
        {
            int ok=0;
            for(int i=0;i<n;i++)
            {
                if(s[i]!=t[i]) {printf("friend!\n");ok=1;break;}
            }
            if(!ok) printf("jntm!\n");
        }
        else if(n<m)
        {
            if(kmp(s,t,a)) {printf("my teacher!\n");}
            else {printf("senior!\n");}
        }
    }
}

E. XKC's basketball team

思路:

先按w值排序.从大到小依次算答案,因为排序,queue也是从大到小入的队列,比当前i点的w+m大的,一定比剩下的w+m大,所以,继续往下寻找最右边的值>w+m的就可以.

代码:

#include<bits/stdc++.h>
#define ll long long
#define inf 0x3f3f3f3f3f3f3f3fLL
#define maxn 500015
using namespace std;
ll n,m,maxr,ans[maxn];
struct AA
{
    ll w,rt;
    bool operator<(const AA&aa)const
    {
        if(w==aa.w) return rt>aa.rt;
        return w>aa.w;
    }
}pos[maxn];
queue<AA>q;
int main()
{
    scanf("%lld%lld",&n,&m);
    for(int i=1;i<=n;i++)
    {
        scanf("%lld",&pos[i].w);
        pos[i].rt=i;
    }
    sort(pos+1,pos+1+n);
    maxr=-1;
    for(int i=1;i<=n;i++)
    {
        while(!q.empty())
        {
            AA x=q.front();
            if(x.w>=pos[i].w+m)
            {
                maxr=max(maxr,x.rt);
                q.pop();
            }
            else break;
        }
        ans[pos[i].rt]=(maxr>pos[i].rt)?(maxr-pos[i].rt-1):(-1);
        q.push(pos[i]);
    }
    for(int i=1;i<=n;i++)
    {
        if(i==n) printf("%lld\n",ans[i]);
        else printf("%lld ",ans[i]);
    }
}

G. Colorful String

思路:马拉车,驾驾驾~

代码:

#include <bits/stdc++.h>
#define rep(i,a,b) for(register int i=(a);i<=(b);i++)
#define dep(i,a,b) for(register int i=(a);i>=(b);i--)
using namespace std;
#define ll long long
const ll mod=1e9+7;
const int maxn=300015;
char s[maxn],t[maxn];
int a[maxn];
int Len[maxn<<1],pos,qian[maxn][27];
char tmp[maxn<<1];
int l,r,len,cnt,num;
int val[maxn];
ll ans;
int search(int la,int lb,int x)
{
    int l=la,r=lb;
    while(l<r)
    {
        int mid=(l+r)>>1;
        if(qian[mid][x]-qian[la-1][x]>0)
        r=mid;
        else l=mid+1;
    }
    return r;
}
ll query(int l,int r)
{
    ll sum=0;
    rep(k,0,25)
    {
        if(qian[r][k]-qian[l-1][k]>0)
        {
            int pos=search(l,r,k);
            //if(cnt==3)
            //cout<<pos<<" "<<l<<" "<<r<<" "<<endl;
            sum+=(r-pos+1);
        }
    }
    return sum;
}
int init(char *st)
{
    int i,len=strlen(st);
    tmp[0]='@';
    for(i=1;i<=2*len;i+=2)
    {
        tmp[i]='#';
        tmp[i+1]=st[i/2];
    }
    tmp[2*len+1]='#';
    tmp[2*len+2]='$';
    tmp[2*len+3]=0;
    return 2*len+1;
}
void manacher(char *st,int len)
{
    int mx=0,po=0;
    for(int i=1;i<=len;i++)
    {
        if(mx>i)
        Len[i]=min(mx-i,Len[2*po-i]);
        else
        Len[i]=1;
        while(st[i-Len[i]]==st[i+Len[i]])
        Len[i]++;
        if(Len[i]+i>mx)
        {
            mx=Len[i]+i;
            po=i;
        }
        l=(i-1)/2-(Len[i]-1)/2;
        r=(i-1)/2+(Len[i]-1)/2;
        if(Len[i]&1) r--;
        //cout<<l<<" "<<r<<endl;
        num=((r-l+2)/2);
        cnt=((i-1)/2)+1;
        if(cnt<=r+1) ans+=query(cnt,r+1);
        //if(l<=r)
         //cout<<l<<" "<<r<<" "<<ans<<endl;
    }
    printf("%lld\n",ans);
    return ;
}
int main()
{
    int T,cas=1;
    scanf("%s",s);
    len=strlen(s);
    rep(i,0,len-1)
    {
        a[i]=s[i]-'a';
        rep(j,0,25)
        qian[i+1][j]=qian[i][j];
        qian[i+1][s[i]-'a']++;
    }
    memset(Len,0,sizeof(Len));
    ans=0;
    len=init(s);
    manacher(tmp,len);
    //printf("%lld\n",ans);
    return 0;
}
/*
babab
*/

K. Center

#include <bits/stdc++.h>
#define rep(i,a,b) for(register int i=(a);i<=(b);i++)
#define dep(i,a,b) for(register int i=(a);i>=(b);i--)
using namespace std;
#define ll long long
const ll mo=5e6+7;
const int maxn=2015;
int a[maxn],n;
ll x[maxn],y[maxn];
ll ans;
map<ll,int>mp,mmp;
map<ll,int>::iterator it,itt;
ll mid(ll a,ll b)
{
    return (a+b)/2;
}
int main()
{
    int T,cas=1;
    scanf("%d",&n);
    rep(i,1,n)
    {
        scanf("%lld%lld",&x[i],&y[i]);
        x[i]*=2;y[i]*=2;
        mmp[x[i]*mo+y[i]]++;
        rep(j,1,i-1)
        mp[mid(x[i],x[j])*mo+mid(y[i],y[j])]++;
    }
    int ans=0;
    ll ansx=0,ansy=0;
    for(it=mp.begin();it!=mp.end();it++)
    {
        int num=(*it).second;
        if(num>ans)
        {
            ans=num;
            ansx=(*it).first/mo;
            ansy=(*it).first%mo;
        }
    }
    ans=n*2+5;
    x[++n]=ansx;
    y[n]=ansy;
    rep(j,1,n)
    {
        mmp.clear();
        rep(i,1,n-1)
        mmp[x[i]*mo+y[i]]++;
        int as=0;
        rep(i,1,n-1)
        {
            ll xx=2*x[j]-x[i];
            ll yy=2*y[j]-y[i];
            if(mmp[xx*mo+yy]==0)
            {
                mmp[xx*mo+yy]++;
                as++;
            }
        }
        if(as<ans) ans=as;
    }
    if(n==1) ans=0;
    printf("%d\n",ans);
    return 0;
}

 

 

 

 

 

 

 

 

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值