C~F Java题解,代码已去除冗余~~~
要么两个点重合,要么较快的点被阻隔一次后跟较慢的点重合,时间复杂度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");
}
}
贪心,最优解一定是尽可能往第一个数上堆值,因此需要把除第一个数外的较大的数字加上去,相同的多个存在,则较靠后的值加上去较优,时间复杂度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();
}
}
}
使得题目要求满足,要么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;
}
}
不妨从中间行开始向两边开始拓展,记录每种末尾的方案数,直到拓展到第一行和最后一行,时间复杂度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);
}
}