浙江省賽 The 16th Zhejiang Provincial Collegiate Programming Contest Sponsored by TuSimple 解題報告

B   Element Swapping

如果(i,j)是答案,那麼容易得到

(i-j)*(a[j]-a[i])=X-\sum_{i=1}^{n}k*a[i]

(i-j)*(a[j]^{2}-a[i]^{2})=Y-\sum_{i=1}^{n}k*a[i]^{2}

兩式子相除得到a[i]+a[j],然後針對右式是否爲0的情況討論一下,再根據第一個式子去判斷一下。

#include<bits/stdc++.h>
#define ll long long
#define inf 0x3f3f3f3f3f3f3f3fLL
#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=100010;
int n,m,k;
ll sum[maxn],x,y,X,Y;
ll ans,ct,cnt,tmp,flag;
struct node
{
    ll v,id;
    bool operator<(node aa)const
    {
        return v<aa.v;
    }
}a[maxn];
int ok[maxn];
int main()
{
    int T,cas=1;
    scanf("%d",&T);
    while(T--){
        scanf("%d%lld%lld",&n,&X,&Y);
        x=X;y=Y;
        rep(i,1,n)
        {
            ok[i]=0;
            scanf("%lld",&a[i].v);
            x-=(ll)i*a[i].v;
            y-=(ll)i*a[i].v*a[i].v;
            a[i].id=i;
        }
        sort(a+1,a+n+1);
        ans=0;
        if(x==0&&y) {puts("0");continue;}
        if(x==0&&y==0)
        {
            int i=1;
            ll tmp=0;
            while(i<=n)
            {
                tmp=0;
                int j=i;
                while(j<=n&&a[j].v==a[i].v) {j++;tmp++;}
                ans+=(tmp*(tmp-1))/2;
                i=j;
            }
            printf("%lld\n",ans);
            continue;
        }
        else if(y%x) {puts("0");continue;}
        else {
            int tim=1;
            y=y/x;
            int i=1,j=n;
            while(i<j)
            {
                tim++;
                int k=i;
                ll tmp=0;
                ll cnt=0;
                while(k<j&&2LL*a[k].v==y&&a[k].v==a[i].v)
                k++;
                if(i!=k) {i=k;continue;}
                tmp=0;
                while(j>i&&a[j].v+a[i].v>y) j--;
                if(j==i) break;
                if(a[i].v+a[j].v!=y) {i++;continue;}
                if(x%(a[j].v-a[i].v)!=0) {i++;continue;}
                ll z=x/(a[j].v-a[i].v);
                //cout<<x<<" "<<a[j].v-a[i].v<<" "<<z<<endl;
                k=i;
                while(k<j&&a[k].v==a[i].v) {
                    if((ll)a[k].id-z<=(ll)n&&(ll)a[k].id-z>0LL)
                    {
                        ok[a[k].id-(int)z]=tim;
                        //cout<<a[k].id<<" "<<z<<endl;
                    }
                    k++;
                }
                while(j>=k&&a[i].v+a[j].v==y) {
                    if(ok[a[j].id]==tim) ans++;
                    j--;
                }
                i=k;
            }
        }
        printf("%lld\n",ans);
      //  if(flag) puts("Yes"); else puts("No");
    }
    return 0;
}

E    Sequence in the Pocket

貪心,每次最大的能不動就不動,若值x動了,那麼小於x的值一定都要按序提到前面去,所以一定是從最大值開始考慮,儘量不動,一個數只有在所有比它大的數的左面,這個數就可以不動,所以權值相同時,還要按下標排序。不過當遇到某數需要前移時,還需考慮,左面,權值相同,並且在所有比它大的數的左面的數不用移動。

#include <bits/stdc++.h>
using namespace std;
#define ll long long int
const int inf=0x3f3f3f3f;
const ll mod=1e9+7;
const int maxn=100005;
int n,ans;
struct AA
{
    int rt,x;
    bool operator<(const AA&aa)const
    {
        if(x==aa.x) return rt<aa.rt;
        return x<aa.x;
    }
}pos[maxn];
int main()
{
   int t;
   scanf("%d",&t);
   while(t--)
   {
       ans=0;
       scanf("%d",&n);
       for(int i=1;i<=n;i++)
       {
           scanf("%d",&pos[i].x);
           pos[i].rt=i;
       }
       sort(pos+1,pos+1+n);
       int l=0,r=1;
       for(int i=n-1;i>=1;i--)
       {
           if(pos[i].rt>pos[i+1].rt) {
                for(int j=i-1;j>=1;j--)
                {
                    if(pos[j].x!=pos[i].x)
                    {
                        r=j+1;break;
                    }
                    if(l==0&&pos[j].rt<pos[i+1].rt)
                    {
                        l=j;
                    }
                }
                ans=i;
                if(l!=0)
                {
                    ans-=l-r+1;
                }
                break;
           }
       }
       printf("%d\n",ans);
   }
   return 0;
}

F Abbreviation

簽到

#include <bits/stdc++.h>
using namespace std;
#define ll long long int
const int inf=0x3f3f3f3f;
double pi=3.141592653589793238462643383279502884;
const ll mod=1e9+7;
const int maxn=300005;
int main()
{
   int t;
   scanf("%d",&t);
   while(t--)
   {
        char s[105];
        scanf("%s",s);
        int len=strlen(s);
        for(int i=0;i<len;i++)
        {
          if(i==0)
          printf("%c",s[i]);
          else
          {
              if(s[i]=='a'||s[i]=='e'||s[i]=='i'||s[i]=='y'||s[i]=='o'||s[i]=='u')
                continue;
              else
                printf("%c",s[i]);
          }
        }
        printf("\n");
   }
   return 0;
}

G  Lucky 7 in the Pocket

#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=200010;
int n,m,k;
int a[maxn],sum[maxn];
int c[maxn];
int ans,ct,cnt,tmp,flag;
char s[maxn];
int main()
{
    int T,cas=1;
    scanf("%d",&n);
    {
        ans=0;   flag=1;
        //memset(c,0,sizeof(c));
        rep(i,1,n){
            scanf("%d",&m);
            while(1)
            {
                if(m%7==0&&m%4!=0) break;
                m++;
            }
            printf("%d\n",m);
        }
        //printf("%d\n",ans);
      //  if(flag) puts("Yes"); else puts("No");
    }
    return 0;
}

H    Singing Everywhere

預處理一個前綴和表示前i個音有多少個跑掉,然後暴力枚舉刪掉哪個就行。複雜度O(n)。

#include<bits/stdc++.h>
#define ll long long
#define inf 0x3f3f3f3f3f3f3f3fLL
#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=100010;
int n,m,k;
ll a[maxn],sum[maxn];
ll ans,ct,cnt,tmp,flag;
char s[maxn];
int main()
{
    int T,cas=1;
    scanf("%d",&T);
    while(T--){
        scanf("%d",&n);
        a[0]=a[n+1]=inf;
        sum[0]=0;
        rep(i,1,n) scanf("%lld",&a[i]);
        if(n<3) {puts("0");continue;}
        rep(i,1,n){
            sum[i]=sum[i-1]+(a[i]>a[i-1]&&a[i]>a[i+1]);
        }
        ans=sum[n];
        if(a[2]>a[1]&&a[2]>a[3])
        ans=min(ans,sum[n]-1);
        if(a[n-1]>a[n-2]&&a[n-1]>a[n])
        ans=min(ans,sum[n]-1);
        rep(i,2,n-1)
        ans=min(ans,sum[n]-sum[i+1]+sum[i-2]+(a[i-1]>a[i-2]&&a[i-1]>a[i+1])+(a[i+1]>a[i-1]&&a[i+1]>a[i+2]));
        printf("%lld\n",ans);
      //  if(flag) puts("Yes"); else puts("No");
    }
    return 0;
}

I    Fibonacci in the Pocket

大數,很容易發現斐波那契數列的前綴和奇偶性爲 奇奇偶  奇奇偶  奇奇偶  奇奇偶

所以只需要模3判斷一下即可。

import java.math.*;
import java.util.*;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.Scanner;
public class Main {
	public static BigInteger zero=new BigInteger("0");
	public static void main(String[] args) {
	Scanner sc = new Scanner(System.in);
	//result.toString();
	int T,cas=1;
	int n,m,cnt=0;
	BigInteger tmp=new BigInteger("0");
	BigInteger aa=new BigInteger("0");
	BigInteger a=new BigInteger("0");
	BigInteger b=new BigInteger("0");
	BigInteger zero=new BigInteger("0");
	BigInteger one=new BigInteger("1");
	BigInteger two=new BigInteger("2");
	BigInteger three=new BigInteger("3");
	n=sc.nextInt();
	while(n>0)
	{
		n--;
		a=sc.nextBigInteger();
		b=sc.nextBigInteger();
		tmp=a.mod(three);
		aa=b.mod(three);
		if(tmp.equals(two)&&!aa.equals(one))
			System.out.println(one);
		else if(!tmp.equals(two)&&aa.equals(one))
			System.out.println(one);
		else System.out.println(zero);
	}
	}
}

J    Welcome Party

並查集+優先隊列,朋友關係是雙向的,不開心的人的數量就是關係圖的塊數,每個塊,需且只需一個人不開心,剩下的人都可以通過關係一個個進屋,不至於不開心,所以並查集判斷關係分塊,選定不開心的人爲下標最小的,讓其成爲塊內最早進屋的,由此決定字典序最小。

然後就用優先隊列,每次選擇可以進屋的人中編號最小的讓其進屋,

首先將所有不高興的人進隊列,選出最小的編號的人,讓其先進屋,然後將其朋友,加入隊列(後面都是沒有加入隊列的加入過隊列即可),在選最小的
 

#include <bits/stdc++.h>
using namespace std;
#define ll long long int
const int inf=0x3f3f3f3f;
const ll mod=1e9+7;
const int maxn=1000005;
int pre[maxn],ans,t[maxn];
int find(int x)
{
   int r=x;
   if(x==pre[x]) return x;
   else
   return pre[x]=find(pre[x]);
}
void join(int x,int y)
{
   int fx=find(x);
   int fy=find(y);
   if(fx!=fy)
   {
       ans--;//cout<<x<<" ! "<<y<<endl;
        if(fx<fy)
        pre[fy]=fx;
        else
        {
            pre[fx]=fy;
        }
   }
   return;
}
struct AA
{
    int v,next;
}pos[maxn*3];
int n,m,a,b,vis[maxn],f[maxn],num,k;
void add(int x,int y)
{
    pos[++num].v=y;
    pos[num].next=f[x];
    f[x]=num;
 
    pos[++num].v=x;
    pos[num].next=f[y];
    f[y]=num;
}
priority_queue<int,vector<int>, greater<int> >pq;
void dfs()
{
    while(!pq.empty())
    {
        int x=pq.top();
        k++;
        if(k==n)
            printf("%d\n",x);
        else printf("%d ",x);
        pq.pop();
        for(int i=f[x];i!=-1;i=pos[i].next)
        {
            int v=pos[i].v;
            if(vis[v]) continue;
            else {vis[v]=1;pq.push(v);}
        }
    }
    return;
}
int main()
{
    int tt;
    scanf("%d",&tt);
    while(tt--)
    {
        while(!pq.empty()) pq.pop();
        scanf("%d%d",&n,&m);
        k=0;
        ans=n;
        for(int i=1;i<=n;i++)
        {
            pre[i]=i;
            vis[i]=0;
            f[i]=-1;
        }
        num=0;
        while(m--)
        {
            scanf("%d%d",&a,&b);
            add(a,b);
            join(a,b);
        }
        printf("%d\n",ans);
        for(int i=1;i<=n;i++)
        {
            if(vis[find(i)]==0)
            {
                vis[find(i)]=1;
                pq.push(find(i));
            }
            else continue;
        }
        dfs();
//        for(int i=1;i<n;i++)
//        {
//            printf("%d ",t[i]);
//        }
//        printf("%d\n",t[n]);
    }
}

K    Strings in the Pocket

這個題其實很水。。。如果S串和T相同,則答案爲迴文子串個數(想想是不是)

如果不同,則從開頭找到第一個不同的位置l,從最後找到第一個不同的位置r,如果l~r翻轉不相同,則答案爲0,否則若S[l-1]==S[r+1],則答案++,l--,r++。
 

#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 int
const int inf=0x3f3f3f3f;
const ll mod=1e9+7;
const int maxn=2000005;
char s[maxn],t[maxn];
int Len[maxn<<1],pos;
char tmp[maxn<<1];
int l,r;
ll ans;
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;
        ans+=((r-l+2)/2);
    }
    printf("%lld\n",ans);
    return ;
}
int main()
{
    int tt;
    scanf("%d",&tt);
    while(tt--)
    {
        ans=0;
        scanf("%s%s",s,t);
        int n=strlen(s);
        l=-1;
        for(int i=0;i<n;i++)
        {
            if(s[i]!=t[i]) {l=i;break;}
        }
        if(l!=-1)
        {
            r=-1;
            for(int i=n-1;i>=0;i--)
            {
                if(s[i]!=t[i]) {r=i;break;}
            }
            int j=r,ok=0;
            for(int i=l;i<=r;i++,j--)
            {
                if(s[i]!=t[j])
                {
                    ok=1;break;
                }
            }
            if(ok)
            {
                printf("0\n");
            }
            else
            {
                ans=1;
                for(int i=1;i<=l&&r+i<n;i++)
                {
                    if(s[l-i]==s[r+i]) ans++;
                    else break;
                }
                printf("%lld\n",ans);
            }
        }
        else///s==t的時候
        {
            int len=init(s);
            manacher(tmp,len);
        }
    }
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章