C~F Java题解,代码已去除冗余~~~

C 至

要么两个点重合,要么较快的点被阻隔一次后跟较慢的点重合,时间复杂度O(1)

import java.util.*;
public class Main{
    public static void main(String args[]){
        Scanner sc=new Scanner(System.in);
        int n=sc.nextInt(),x1=sc.nextInt(),y1=sc.nextInt(),x2=sc.nextInt(),y2=sc.nextInt();
        System.out.println(x1+y1==x2+y2||x1==1&&x2==2&&y1==y2-1&&y2<n-1||x2==1&&x1==2&&y2==y1-1&&y1<n-1?"YES":"NO");
    }
}

D 死

贪心,最优解一定是尽可能往第一个数上堆值,因此需要把除第一个数外的较大的数字加上去,相同的多个存在,则较靠后的值加上去较优,时间复杂度O(Tnlogn)

import java.util.*;
public class Main{
    public static void main(String args[]){
        Scanner sc=new Scanner(System.in);
        for(int j=sc.nextInt();j!=0;j--){
            int n=sc.nextInt(),k=sc.nextInt();
            long head=sc.nextInt();
            Queue<int[]> q=new PriorityQueue<>((a,b)->a[0]==b[0]?b[1]-a[1]:b[0]-a[0]);
            for(int i=2;i<=n;i++){
                q.add(new int[]{sc.nextInt(),i});
            }
            for(int i=0;i<k;i++){
                head+=q.poll()[0];
            }
            List<int[]> list=new ArrayList<>(q);
            Collections.sort(list,(a,b)->a[1]-b[1]);
            System.out.print(head+" ");
            for(int a[]:list){
                System.out.print(a[0]+" ");
            }
            System.out.println();
        }
    }
}

E 不

使得题目要求满足,要么mex是正数,且比最大值大,要么mex是0,且序列单值,计数统计即可,时间复杂度O(nlogn)

import java.util.*;
public class Main{
    static int mod=(int)1e9+7;
    public static void main(String args[]){
        Scanner sc=new Scanner(System.in);
        int n=sc.nextInt(),count[]=new int[n+5];
        for(int i=0;i<n;i++){
            count[sc.nextInt()]++;
        }
        long ans=0,num=pow(2,count[0])-1;
        for(int i=0;i<=n;num=num*(pow(2,count[i+1])-1)%mod,i++){
            ans=(ans+num)%mod;
            if(i!=0){
                ans=(ans+pow(2,count[i])-1)%mod;
            }
        }
        System.out.println(ans);
    }
    static long pow(long a,long b){
        long ans=1;
        for(;b!=0;b>>=1,a=a*a%mod){
            if(b%2==1){
                ans=ans*a%mod;
            }
        }
        return ans;
    }
}

F 渝

不妨从中间行开始向两边开始拓展,记录每种末尾的方案数,直到拓展到第一行和最后一行,时间复杂度O(n^3)

import java.util.*;
public class Main{
    static int mod=(int)1e9+7,move[][]={{0,0},{0,1},{-1,0},{-1,1}};
    public static void main(String args[]){
        Scanner sc=new Scanner(System.in);
        int n=sc.nextInt(),a[][]=new int[n][];
        for(int j=0;j<n;j++){
            a[j]=new int[j+1];
            for(int k=0;k<=j;k++){
                a[j][k]=sc.nextInt();
            }
        }
        long count[][]=new long[n+5][n+5],ans=0;
        if(n%2==1){
            //n为奇数,中间的一行直接n/2
            for(int j=0;j<=n/2;j++){
                count[j][j]=1;
            }
        }
        else{
            //否则直接为n/2-1,n/2
            for(int j=0;j<n/2;j++){
                if(a[n/2-1][j]==a[n/2][j]){
                    count[j][j]=1;
                }
                if(a[n/2-1][j]==a[n/2][j+1]){
                    count[j][j+1]=1;
                }
            }
        }
        //较小的是(n-1)/2,较大的是n-1-(n-1)/2
        for(int l=(n-1)/2-1,r=n-1-(n-1)/2+1;l>=0;l--,r++){
            long temp[][]=new long[n+5][n+5];
            //temp的值需从l+1和r-1行
            for(int i=0;i<n;i++){
                for(int j=0;j<n;j++){
                    for(int mo[]:move){
                        int x=i+mo[0],y=j+mo[1];
                        if(x>=0&&x<=l&&y>=0&&y<=r&&a[l][x]==a[r][y]){
                            temp[x][y]=(temp[x][y]+count[i][j])%mod;
                        }
                    }
                }
            }
            count=temp;
        }
        for(int j=0;j<n;j++){
            ans+=count[0][j];
        }
        System.out.println(ans%mod);
    }
}