蓝桥杯
寄巧
双端队列模拟栈和队列Deque<Integer> queue=new ArrayDeque<>();
queue.offer(last) //入队
queue.poll() //出队
queue.peek() //查看队首元素
queue.
需要排序用优先队列,PriorityQueue默认是小根堆
Comparator<Integer> cp=(o1,o2)-> o2-o1; //比较器
PriorityQueue<Integer> pq=new PriorityQueue<Integer>(cp);
用Integer.toString(i);和str.charAt(j)-'0';来正着取一个数的每一位
Integer.parseInt(s2.substring(0, id));将全是数字的字符串转为int变量
s.contains("-")判断字符串中是否存在字符
String s1[]=s.split("=");以=为分界线分开字符串
Double.MAX_VALUE;表示Double的最大值
Arrays.sort(range, 0, n)数组排序范围是左闭右开,也就是[0,n)
//MAP的操作
HashMap<Integer,Integer> map=new HashMap<Integer, Integer>();
map.put(t,map.getOrDefault(t, 0)+1);
注意int的最大为2e9,long为1e18
对数组进行自定义排序
Arrays.sort(people, (a, b) -> a.age - b.age);//前-后,为升序排序
Comparable接口
-
this-other为升序,ohter-this为降序public int compareTo(Student other) { return this.score - other.score; // 升序 } -
在这个例子中,是按照r来升序排序。
Integer.compare(r, o.r);相当于r-o.rclass Range implements Comparable<Range>{ int l,r; public Range(int l,int r) { this.l=l; this.r=r; } public int compareTo(Range o) { return Integer.compare(r, o.r); } }
每日一题
农夫约翰的奶酪块(用二维模拟三维)

import java.util.*;
public class Main {
static int N=1020,n,q,ans;
static int[][] xy=new int[N][N],yz=new int[N][N],xz=new int[N][N];
public static void main(String[] args) {
Scanner scan=new Scanner(System.in);
n=scan.nextInt();
q=scan.nextInt();
while (q-- > 0)
{
int x= scan.nextInt();
int y= scan.nextInt();
int z= scan.nextInt();
if((++xy[x][y])==n) ans++;
if((++yz[y][z])==n) ans++;
if((++xz[x][z])==n) ans++;
System.out.println(ans);
}
}
}
哞叫时间(枚举)

先枚举哪一位变,再枚举变了之后的叫声
import javax.swing.*;
import java.util.*;
public class Main {
static int N=20010,n,f,ans;
static int [] str=new int[N],str1=new int[N];
static int[][] cont=new int[26][26],cont1=new int[26][26];
static boolean[][] st=new boolean[26][26];
static String line="";
static boolean checkstr(int i)
{
return str[i]!=26&&str[i+1]!=26&&str[i+2]!=26;
}
static void check()
{
for(int i=0;i<26;i++)
for(int j=0;j<26;j++) cont1[i][j]=0;
for(int i=0;i<n-2;i++)
{
if(str1[i+1]==str1[i+2]&&str1[i]!=str1[i+1])
{
cont1[str1[i]][str1[i+1]]++;
// System.out.println(cont1[str1[i]][str1[i+1]]+" "+(char)(str1[i]+'a')+(char)(str1[i+1]+'a')+(char)(str1[i+2]+'a'));
if(cont1[str1[i]][str1[i+1]]>=f&&!st[str1[i]][str1[i+1]])
{
// System.out.println(cont1[str1[i]][str1[i+1]]+" "+(char)(str1[i]+'a')+(char)(str1[i+1]+'a')+(char)(str1[i+2]+'a'));
st[str1[i]][str1[i+1]]=true;
ans++;
}
}
}
}
static void print()
{
for(int i=0;i<n;i++)
{
System.out.print((char)(str1[i]+'a')+" ");
}
System.out.println();
}
public static void main(String[] args) {
Scanner scan=new Scanner(System.in);
n= scan.nextInt();
f= scan.nextInt();
line=scan.next();
for(int i=0;i<n;i++)
{
str[i]=(int)line.charAt(i)-'a';
// System.out.print(str[i]+" ");
}
// System.out.println();
for(int i=0;i<n;i++)
{
for(int j=0;j<n;j++)
{
str1[j]=str[j];
}
for(int j=0;j<=25;j++)
{
str1[i]=j;
// print();
check();
}
}
System.out.println(ans);
for(int i=0;i<26;i++)
for(int j=0;j<26;j++)
{
if(st[i][j]) System.out.println(""+(char)(i+'a')+(char)(j+'a')+(char)(j+'a'));
}
}
}
哞叫时间II(枚举)

先从前往后枚举每个数字出现多少次,用l[]来表示这个数出现的次数。
然后从后向前枚举每个数字,用r[]表示每个数字出现的次数,每次枚举都让l[]对应的数减1,如果减到0就说明这个数字不在左边了。
import java.io.*;
import java.util.*;
public class Main {
public static StreamTokenizer cin=new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
public static PrintWriter cout=new PrintWriter(new OutputStreamWriter(System.out));
static int N=(int)1e6+3,n;
static long ans;
static int[] l=new int[N],r=new int[N];
public static void main(String[] args) throws IOException {
n=nextInt();
int[] a=new int[n+1];
int cnt=0;
for(int i=1;i<=n;i++)
{
a[i]=nextInt();
l[a[i]]++;
if(l[a[i]]==1) cnt++;
}
for(int i=n;i>=1;i--)
{
l[a[i]]--;r[a[i]]++;
if(l[a[i]]==0) cnt--;
if(r[a[i]]==2)
{
ans+=cnt;
if(l[a[i]]!=0) ans--;
}
}
cout.println(ans);
cout.flush();
}
public static int nextInt() throws IOException {
cin.nextToken();
return (int)cin.nval;
}
public static long nextLong() throws IOException {
cin.nextToken();
return (long)cin.nval;
}
public static double nextDouble() throws IOException {
cin.nextToken();
return cin.nval;
}
public static String nextString() throws IOException {
cin.nextToken();
return cin.sval;
}
public static void closeAll()
{
cout.close();
}
}
试除法求约数
package Main;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.StreamTokenizer;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Collections;
public class Main {
public static StreamTokenizer cin=new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
public static PrintWriter cout=new PrintWriter(new OutputStreamWriter(System.out));
static ArrayList<Integer> get_divisors(int n)
{
ArrayList<Integer> list=new ArrayList<Integer>();
for(int i=1;i<=n/i;i++)
if(n%i==0)
{
list.add(i);
if(i!=n/i) list.add(n/i);
}
Collections.sort(list)
return list;
}
public static void main(String[] args) throws IOException {
int n=nextInt();
while(n-- > 0)
{
int x;
x=nextInt();
ArrayDeque<Integer> queue=get_divisors(x);
for(Integer t:queue) cout.print(t+" ");
cout.println();
}
cout.flush();
}
public static int nextInt() throws IOException {
cin.nextToken();
return (int)cin.nval;
}
public static long nextLong() throws IOException {
cin.nextToken();
return (long)cin.nval;
}
public static double nextDouble() throws IOException {
cin.nextToken();
return cin.nval;
}
public static String nextString() throws IOException {
cin.nextToken();
return cin.sval;
}
public static void closeAll()
{
cout.close();
}
}
14届Java B
互质(快速幂求逆元,容斥原理,互质定义)


package lqb;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.StreamTokenizer;
public class Main {
// public static StreamTokenizer cin=new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
// public static PrintWriter cout=new PrintWriter(new OutputStreamWriter(System.out));
static StreamTokenizer cin=new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
static PrintWriter cout=new PrintWriter(new OutputStreamWriter(System.out));
static int N=20,INF=0x3f3f3f3f,MOD=1000000007;
static int[] p=new int[N];
static long qmi(int m,int k)
{
long res=1,t=m;
while(k!=0)
{
if((k&1)==1) res=res*t%MOD;
t=t*t%MOD;
k>>=1;
}
return res;
}
public static void main(String[] args) throws IOException
{
long sum=qmi(2023,2023);
long a=sum*qmi(7,MOD-2)%MOD;
long b=sum*qmi(17,MOD-2)%MOD;
long c=sum*qmi(7*17,MOD-2)%MOD;
// long a=(sum/7)%MOD;
// long b=(sum/17)%MOD;`
// long c=(sum/qmi(7*17,MOD-2))%MOD;
long ans=(sum-(a+b-c)+2*MOD)%MOD;
cout.print(ans);
cout.flush();
}
public static int nextInt() throws IOException {
cin.nextToken();
return (int)cin.nval;
}
public static long nextLong() throws IOException {
cin.nextToken();
return (long)cin.nval;
}
public static double nextDouble() throws IOException {
cin.nextToken();
return cin.nval;
}
public static String nextString() throws IOException {
cin.nextToken();
return cin.sval;
}
public static void closeAll()
{
cout.close();
}
}
- 看到\(2023^{2023}\)不要怕,因为有MOD 1e9+7 ,所以用快速幂一定可以求出来
- 两个数互质,则两个数没有除 1 以外的其他公约数。如果两个数是素数,则一定互质
逆元(快速幂求逆元,暴力)

直接用快速幂求逆元,然后暴力就行,就是时间需要一两分钟左右
package lqb;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.StreamTokenizer;
public class Main {
// public static StreamTokenizer cin=new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
// public static PrintWriter cout=new PrintWriter(new OutputStreamWriter(System.out));
static StreamTokenizer cin=new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
static PrintWriter cout=new PrintWriter(new OutputStreamWriter(System.out));
static int N=20,INF=0x3f3f3f3f,MOD=2146516019;
static int[] p=new int[N];
static long qmi(long m,long k)
{
long res=1,t=m;
while(k!=0)
{
if((k&1)==1) res=res*t%MOD;
t=t*t%MOD;
k>>=1;
}
return res;
}
public static void main(String[] args) throws IOException
{
long res=0;
for(long i=1;i<=233333333;i++)
{
long t=qmi(i,2146516019-2);
cout.println(t);
res^=t;
}
cout.print("-------------------------");
cout.print(res);
cout.flush();
}
public static int nextInt() throws IOException {
cin.nextToken();
return (int)cin.nval;
}
public static long nextLong() throws IOException {
cin.nextToken();
return (long)cin.nval;
}
public static double nextDouble() throws IOException {
cin.nextToken();
return cin.nval;
}
public static String nextString() throws IOException {
cin.nextToken();
return cin.sval;
}
public static void closeAll()
{
cout.close();
}
}
- 这里比较凑巧了,正好在运行,然后就拿笔想算一下怎么算的,正在想就算出来了。
玩具(贪心)

一开始根据题意想到区间dp中的石子合并问题,但是那个问题是要求只能合并相邻两个,而这里没有这个限制,同时那个要求合并为一堆,这个不需要。这里和哈夫曼树的合并果子问题也不一样
这里的思路是先排序,然后取最大和最小的乘积贡献到答案中即可。
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.StreamTokenizer;
import java.util.Arrays;
public class Main {
// public static StreamTokenizer cin=new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
// public static PrintWriter cout=new PrintWriter(new OutputStreamWriter(System.out));
static StreamTokenizer cin=new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
static PrintWriter cout=new PrintWriter(new OutputStreamWriter(System.out));
static int N=2000005,n;
static long[] w=new long[N];
public static void main(String[] args) throws IOException
{
n=nextInt();
for(int i=0;i<2*n;i++) w[i]=nextInt();
Arrays.sort(w,0,2*n);
// for(int i=0;i<2*n;i++) cout.println(w[i]);
long res=0;
for(int i=0,j=2*n-1;i<j;i++,j--)
{
res+=w[i]*w[j];
// cout.println(w[i]+" "+w[j]);
}
cout.println(res);
cout.flush();
}
public static int nextInt() throws IOException {
cin.nextToken();
return (int)cin.nval;
}
public static long nextLong() throws IOException {
cin.nextToken();
return (long)cin.nval;
}
public static double nextDouble() throws IOException {
cin.nextToken();
return cin.nval;
}
public static String nextString() throws IOException {
cin.nextToken();
return cin.sval;
}
public static void closeAll()
{
cout.close();
}
}
不完整的算式(大模拟)


没有用API写的
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.StreamTokenizer;
public class Main {
// public static StreamTokenizer cin=new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
// public static PrintWriter cout=new PrintWriter(new OutputStreamWriter(System.out));
static StreamTokenizer cin=new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
static PrintWriter cout=new PrintWriter(new OutputStreamWriter(System.out));
static BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));
static String str;
static char[] c;
static int get_num(int st,int ed)
{
int t=1;
int num=0;
for(int i=ed-1;i>=st;i--)
{
num+=(c[i]-'0')*t;
t*=10;
}
return num;
}
public static void main(String[] args) throws IOException
{
str=bf.readLine();
char[] c=str.toCharArray();
int sym=0;
while((c[sym]<='9'&&c[sym]>='0')||c[sym]=='?') sym++;
// cout.println(sym+" "+c[sym]);
if(c[sym]=='=') //1?1=2
{
int eq=sym;
sym=0;
while(c[sym]<='9'&&c[sym]>='0') sym++;
// cout.println(sym+" "+c[sym]);
// cout.println(eq+" "+c[eq]);
long num1=0,num2=0,num3=0;
long t=1;
for(int i=sym-1;i>=0;i--)
{
num1+=(c[i]-'0')*t;
t*=10;
}
t=1;
for(int i=eq-1;i>sym;i--)
{
num2+=(c[i]-'0')*t;
t*=10;
}
t=1;
int ed=str.length();
for(int i=ed-1;i>eq;i--)
{
num3+=(c[i]-'0')*t;
t*=10;
}
// cout.println(num1+" "+num2+" "+num3);
if(num1+num2==num3) cout.println("+");
else if(num1-num2==num3) cout.println("-");
else if(num1*num2==num3) cout.println("*");
else cout.println("/");
}
else
{
int num1=0,num2=0,num3=0;
int t=1;
int que=0;
while((c[que]<='9'&&c[que]>='0')||c[que]=='+'||c[que]=='-'||c[que]=='*'||c[que]=='/'||c[que]=='=') que++;
// cout.println(que+" "+c[que]);
int eq=str.length()-1;
while((c[eq]<='9'&&c[eq]>='0')||c[eq]=='?') eq--;
// cout.println(eq+" "+c[eq]);
if(que<eq&&que>sym) //1+?=2
{
for(int i=sym-1;i>=0;i--)
{
num1+=(c[i]-'0')*t;
t*=10;
}
t=1;
int ed=str.length();
for(int i=ed-1;i>eq;i--)
{
num3+=(c[i]-'0')*t;
t*=10;
}
// cout.println(num1+" "+num2+" "+num3);
if(c[sym]=='+')
{
num2=num3-num1;
cout.println(num2);
}
else if(c[sym]=='-')
{
num2=num1-num3;
cout.println(num2);
}
else if(c[sym]=='*')
{
num2=num3/num1;
cout.println(num2);
}
else
{
num2=num1/num3;
cout.println(num2);
}
}
else if(sym<eq&&eq<que) //1+1=?
{
for(int i=sym-1;i>=0;i--)
{
num1+=(c[i]-'0')*t;
t*=10;
}
t=1;
for(int i=eq-1;i>sym;i--)
{
num2+=(c[i]-'0')*t;
t*=10;
}
// cout.println(num1+" "+num2+" "+num3);
if(c[sym]=='+') cout.println(num1+num2);
else if(c[sym]=='-') cout.println(num1-num2);
else if(c[sym]=='*') cout.println(num1*num2);
else cout.println(num1/num2);
}
else //?+1=2
{
for(int i=eq-1;i>sym;i--)
{
num2+=(c[i]-'0')*t;
t*=10;
}
t=1;
for(int i=str.length()-1;i>eq;i--)
{
num3+=(c[i]-'0')*t;
t*=10;
}
// cout.println(num1+" "+num2+" "+num3);
if(c[sym]=='+') cout.println(num3-num2);
else if(c[sym]=='-') cout.println(num2+num3);
else if(c[sym]=='*') cout.println(num3/num2);
else cout.println(num2*num3);
}
}
cout.flush();
}
public static int nextInt() throws IOException {
cin.nextToken();
return (int)cin.nval;
}
public static long nextLong() throws IOException {
cin.nextToken();
return (long)cin.nval;
}
public static double nextDouble() throws IOException {
cin.nextToken();
return cin.nval;
}
public static String nextString() throws IOException {
cin.nextToken();
return cin.sval;
}
public static void closeAll()
{
cout.close();
}
}
用API写的
import java.util.Scanner;
public class l17135 {
public static void main(String[] args) {
Scanner scanner=new Scanner(System.in);
String s=scanner.nextLine();
//System.out.println(s);
if(s.contains("+")||s.contains("-")||s.contains("*")||s.contains("/")) {
//缺ABC
String s1[]=s.split("=");
//缺c
String s2=s1[0];
if(s1[1].equals("?")) {
int id=0;
for(int i=0;i<s2.length();i++) {
if(s2.charAt(i)<'0'||s2.charAt(i)>'9') {
id=i;
break;
}
}
int a=Integer.parseInt(s2.substring(0, id));
int b=Integer.parseInt(s2.substring(id+1, s2.length()));
if(s.contains("+"))System.out.println(a+b);
if(s.contains("-"))System.out.println(a-b);
if(s.contains("*"))System.out.println(a*b);
if(s.contains("/"))System.out.println(a/b);
}else {
//缺ab
int c=Integer.parseInt(s1[1]);
int id=0;
for(int i=0;i<s2.length();i++) {
if(s2.charAt(i)=='+'||s2.charAt(i)=='-'||s2.charAt(i)=='*'||s2.charAt(i)=='/') {
id=i;
break;
}
}
int a=0;
if(s2.charAt(id-1)>='0'&&s2.charAt(id-1)<='9') {
a=Integer.parseInt(s2.substring(0, id));
if(s.contains("/"))System.out.println(a/c);
}else {
a=Integer.parseInt(s2.substring(id+1, s2.length()));
if(s.contains("/"))System.out.println(c*a);
}
if(s.contains("+"))System.out.println(c-a);
if(s.contains("-"))System.out.println(c+a);
if(s.contains("*"))System.out.println(c/a);
}
}else {//缺+-*/
String s1[]=s.split("=");
int c=Integer.parseInt(s1[1]);
String s2=s1[0];
int id=0;
for(int i=0;i<s2.length();i++) {
if(s2.charAt(i)<'0'||s2.charAt(i)>'9') {
id=i;
break;
}
}
int a=Integer.parseInt(s2.substring(0, id));
int b=Integer.parseInt(s2.substring(id+1, s2.length()));
//System.out.println(a+" "+b+" "+c);
if(a+b==c)System.out.println("+");
if(a-b==c)System.out.println("-");
if(a*b==c)System.out.println("*");
if(a/b==c)System.out.println("/");
}
}
}
s.contains("+")查看字符串有没有某一项String[] s1=s.split("=");分割字符串,要用字符串数组接收
星球(状压dp,记忆化搜索)

状态表示dp[s][j]
- 集合:s表示所有星球的状态,为1表示打过。
j表示从第j个星球出发。dp[s][j]表示从状态s和星球j出发攻打的最小代价 - 属性:min
状态计算:
dp[s][i]=min(dp[s|(1<<j)][k]+dis(i,j)*range[j].w),s|(1<<j)表示之前如何没打过第j个星球,那就从现在的星球到第j个星球上打。
这里要注意从哪个星球开始,哪个星球的状态为1。
由于我们的写法问题,这里不能虚构出一个距离所有点都为0代价的虚构点,还是要挨个枚举的
package lqb;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.StreamTokenizer;
import java.util.Arrays;
class Range{
double x,y,z,w;
public Range(double x,double y,double z,double w) {
this.x=x;
this.y=y;
this.z=z;
this.w=w;
}
}
public class Main {
// public static StreamTokenizer cin=new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
// public static PrintWriter cout=new PrintWriter(new OutputStreamWriter(System.out));
static StreamTokenizer cin=new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
static PrintWriter cout=new PrintWriter(new OutputStreamWriter(System.out));
static BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));
static double dis(Range a,Range b)
{
return Math.sqrt(( (a.x-b.x)*(a.x-b.x) + (a.y-b.y)*(a.y-b.y) + (a.z-b.z)*(a.z-b.z) ));
}
static double dfs(int s,int i) //初始状态为s,从i星球开始。注意开始的星球状态要为1
{
if(s==(1<<n)-1) return 0;
if(dp[s][i]!=-1) return dp[s][i];
double res=Double.MAX_VALUE;
for(int j=0;j<n;j++)
{
if(((s>>j)&1)==1) continue;
res=Math.min(res,dfs(s|(1<<j),j)+dis(range[i],range[j])*range[j].w );
}
dp[s][i]=res;
return res;
}
static Range[] range=new Range[20];
static double[][] dp;
static int n=0;
public static void main(String[] args) throws IOException
{
n=nextInt();
dp=new double[1<<n][n];
for(double[] t:dp) Arrays.fill(t, -1);
for(int i=0;i<n;i++)
{
range[i]=new Range(nextDouble(),nextDouble(),nextDouble(),nextDouble());
}
double ans=Double.MAX_VALUE;
for(int i=0;i<n;i++)
{
ans=Math.min(ans,dfs(0|(1<<i),i));
}
cout.printf("%.2f",ans);
cout.flush();
}
public static int nextInt() throws IOException {
cin.nextToken();
return (int)cin.nval;
}
public static long nextLong() throws IOException {
cin.nextToken();
return (long)cin.nval;
}
public static double nextDouble() throws IOException {
cin.nextToken();
return cin.nval;
}
public static String nextString() throws IOException {
cin.nextToken();
return cin.sval;
}
public static void closeAll()
{
cout.close();
}
}
序列(数学,审题)

这题的审题从一开始就有问题,没读懂题意
- 题目说是\((a_i,b_i)\),我理解成是两个序列中任意两个数了
- 题目说求\(S_i\)从1到n,也就说有n个b数组,我没看到以为是没有数量限制
具体思路是对于每一个a[i](i从1开始),求与i的最小公倍数,然后用n*i除以最小公倍数得到对于a[i]来说有几个序列。
package lqb;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.StreamTokenizer;
public class Main {
// public static StreamTokenizer cin=new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
// public static PrintWriter cout=new PrintWriter(new OutputStreamWriter(System.out));
static StreamTokenizer cin=new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
static PrintWriter cout=new PrintWriter(new OutputStreamWriter(System.out));
static BufferedReader bf=new BufferedReader(new InputStreamReader(System.in));
static long n;
static long[] a;
static long gcd(long a,long b)
{
return b!=0?gcd(b,a%b):a;
}
static long lcm(long a,long b)
{
return a*b/gcd(a,b);
}
public static void main(String[] args) throws IOException
{
n=nextInt();
a=new long[(int)n+1];
long res=0;
for(int i=1;i<=n;i++)
{
a[i]=nextInt();
long t=lcm(i,a[i]);
res+=((long)i*n)/t;
}
cout.print(res);
cout.flush();
}
public static int nextInt() throws IOException {
cin.nextToken();
return (int)cin.nval;
}
public static long nextLong() throws IOException {
cin.nextToken();
return (long)cin.nval;
}
public static double nextDouble() throws IOException {
cin.nextToken();
return cin.nval;
}
public static String nextString() throws IOException {
cin.nextToken();
return cin.sval;
}
public static void closeAll()
{
cout.close();
}
}
- 注意审题,这题一开始审题出问题了!
电动车(kruskal求最小生成树变种)

这里要求一个最小生成树中两个点的最大路径,用kruskal求最小生成树,求的过程中把最大路径算出来即可
package lqb;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.StreamTokenizer;
import java.util.Arrays;
class Edgs implements Comparable<Edgs>{
int u,v,w;
public Edgs(int u,int v,int w)
{
this.u=u;this.v=v;this.w=w;
}
@Override
public int compareTo(Edgs o) {
return this.w-o.w;
}
}
public class Main {
// public static StreamTokenizer cin=new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
// public static PrintWriter cout=new PrintWriter(new OutputStreamWriter(System.out));
static StreamTokenizer cin=new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
static PrintWriter cout=new PrintWriter(new OutputStreamWriter(System.out));
static BufferedReader bf=new BufferedReader(new InputStreamReader(System.in));
static int N=200010,n,m,w,INF=0x3f3f3f3f;
static Edgs[] edgs=new Edgs[N];
static int[] p=new int[N];
public static int find(int x)
{
if(p[x]!=x) p[x]=find(p[x]);
return p[x];
}
public static int kruskal() {
Arrays.sort(edgs,0,m);
for(int i=0;i<=n;i++) p[i]=i;
int res=0;
int cnt=0;
for(int i=0;i<m;i++)
{
int u=edgs[i].u;
int v=edgs[i].v;
int w=edgs[i].w;
int a=find(u),b=find(v);
if(a!=b)
{
p[a]=b;
res=w;
cnt++;
}
}
// cout.println(cnt);
if(cnt<n-1) return -1;
return res;
}
public static void main(String[] args) throws IOException
{
n=nextInt();m=nextInt();
for(int i=0;i<m;i++)
{
edgs[i]=new Edgs(nextInt(),nextInt(),nextInt());
}
int ans=kruskal();
cout.println(ans);
cout.flush();
}
public static int nextInt() throws IOException {
cin.nextToken();
return (int)cin.nval;
}
public static long nextLong() throws IOException {
cin.nextToken();
return (long)cin.nval;
}
public static double nextDouble() throws IOException {
cin.nextToken();
return cin.nval;
}
public static String nextString() throws IOException {
cin.nextToken();
return cin.sval;
}
public static void closeAll()
{
cout.close();
}
}
- 这里一开始审题又出现问题了,“使得不需要在任何高速公路内补充电量”这句理解成了求最小生成树的权值了。但是这里说的是“任何高速公路内”,不是“任何城市的路途间”
游戏(滑动窗口)

先用单调队列求出每个窗口的最大值和最小值。通过数学关系可以知道, max_list和min_list为每个窗口的最大值和最小值,则总合为n*max_list[1]-(min_list[1]+min_list[2]...min_list[n])+n*max_list[2]-(min_list[1]+min_list[2]...min_list[n])整理一下得到n*(max_list[1]+max_list[2...])-n*(min_list[1]+min_list[2]...)。因为是有n^2 个,所以要除n^2 得到最后答案
package lqb;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.StreamTokenizer;
import java.util.ArrayList;
import java.util.List;
import java.util.PriorityQueue;
public class Main {
// public static StreamTokenizer cin=new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
// public static PrintWriter cout=new PrintWriter(new OutputStreamWriter(System.out));
static StreamTokenizer cin=new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
static PrintWriter cout=new PrintWriter(new OutputStreamWriter(System.out));
static BufferedReader bf=new BufferedReader(new InputStreamReader(System.in));
static int N=100005,n,k;
static int[] arr=new int[N];
public static void main(String[] args) throws IOException
{
n=nextInt();k=nextInt();
for(int i=0;i<n;i++) arr[i]=nextInt();
// --- 初始化数据结构 ---
// 最大堆(降序排序):堆顶是当前窗口可能的最大值,存储格式:[value, index]
PriorityQueue<int[]> max = new PriorityQueue<>((o1, o2) -> o2[0] - o1[0]);
// 最小堆(升序排序):堆顶是当前窗口可能的最小值,存储格式:[value, index]
PriorityQueue<int[]> min = new PriorityQueue<>((o1, o2) -> o1[0] - o2[0]);
// 用于存储每个窗口的最大值和最小值
List<Integer> max_list = new ArrayList<>();
List<Integer> min_list = new ArrayList<>();
// --- 1. 初始化填充前 div-1 个元素(窗口未满时的预填充)---
for (int i = 0; i < div - 1; i++) {
max.add(new int[]{arr[i], i}); // 加入最大堆
min.add(new int[]{arr[i], i}); // 加入最小堆
}
// --- 2. 滑动窗口主循环(从 div-1 开始完整覆盖窗口)---
for (int i = div - 1; i < arr.length; i++) {
// 2.1 将新元素加入堆
max.add(new int[]{arr[i], i});
min.add(new int[]{arr[i], i});
// 2.2 计算当前窗口最大值
while (!max.isEmpty()) {
int[] poll = max.peek(); // 查看堆顶元素
if (i - poll[1] < div) { // 如果该元素的索引仍在窗口内
max_list.add(poll[0]); // 存入最大值列表
break;
} else {
max.poll(); // 否则移除过期元素,继续检查下一个
}
}
// 2.3 计算当前窗口最小值
while (!min.isEmpty()) {
int[] poll = min.peek();
if (i - poll[1] < div) { // 检查是否在窗口内
min_list.add(poll[0]); // 存入最小值列表
break;
} else {
min.poll(); // 移除过期元素
}
}
}
double ans=0;
for(int i=0;i<max_list.size();i++)
{
ans+=max_list.get(i)-min_list.get(i);
}
ans/=max_list.size();
cout.printf("%.2f",ans);
cout.flush();
}
public static int nextInt() throws IOException {
cin.nextToken();
return (int)cin.nval;
}
public static long nextLong() throws IOException {
cin.nextToken();
return (long)cin.nval;
}
public static double nextDouble() throws IOException {
cin.nextToken();
return cin.nval;
}
public static String nextString() throws IOException {
cin.nextToken();
return cin.sval;
}
public static void closeAll()
{
cout.close();
}
}
- 滑动窗口主要是检查当前优先队列的第一个是不是在范围内,如果不是就丢掉找下一个,直到在氛围内,不用对于不在范围内但是在有限队列中的数特殊处理
非对称二叉树(dp)

import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int k = sc.nextInt();
// dp[i][j] 表示节点个数为i时,树的最大高度为j时,非对称二叉树的数量
long[][] dp = new long[n + 1][n + 1];
dp[1][1] = dp[0][0] = 1;
// 枚举所有点的数量i
// 除去根节点后,枚举所有左子树点的数量x,右子树点的数量y
// 对于左子树枚举所有高度c,对于右子树枚举所有高度d
// 找到满足题目要求的情况,就将左右两侧的可能情况数量相乘,加入到目标dp中
for (int i = 2; i <= n; i++) {
for (int x = 0; x < i; x++) {
int y = i - x - 1;
for (int c = 0; c <= x; c++) {
for (int d = 0; d <= y; d++) {
if (Math.max(c, d) >= k * Math.min(c, d)) {
dp[i][Math.max(c, d) + 1] += dp[x][c] * dp[y][d];
}
}
}
}
}
long ans = 0;
for (int i = 1; i <= n; i++) {
ans += dp[n][i];
}
System.out.print(ans);
}
}
数和游戏(没看,太难)
14届C B
子2023(纯暴力)

解法1(纯暴力)
把字符串拼接到一起,然后从头开始枚举
package lqb;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.StreamTokenizer;
public class Main {
// public static StreamTokenizer cin=new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
// public static PrintWriter cout=new PrintWriter(new OutputStreamWriter(System.out));
static StreamTokenizer cin=new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
static PrintWriter cout=new PrintWriter(new OutputStreamWriter(System.out));
static BufferedReader bf=new BufferedReader(new InputStreamReader(System.in));
public static void main(String[] args) throws IOException
{
StringBuilder str=new StringBuilder();
for(int i=1;i<=2023;i++)
{
str.append(Integer.toString(i));
// char[] s=Integer.toString(i).toCharArray();
// for(char t:s)
// {
// if(t=='2'||t=='0'||t=='3') str.append(t);
// }
}
long ans=0;
for(int i=0;i<str.length();i++)
{
if(str.charAt(i)!='2') continue;
for(int j=i+1;j<str.length();j++)
{
if(str.charAt(j)!='0') continue;
for(int k=j+1;k<str.length();k++)
{
if(str.charAt(k)!='2') continue;
for(int l=k+1;l<str.length();l++)
{
if(str.charAt(l)!='3') continue;
ans++;
}
}
}
}
cout.println(ans);
cout.flush();
}
public static int nextInt() throws IOException {
cin.nextToken();
return (int)cin.nval;
}
public static long nextLong() throws IOException {
cin.nextToken();
return (long)cin.nval;
}
public static double nextDouble() throws IOException {
cin.nextToken();
return cin.nval;
}
public static String nextString() throws IOException {
cin.nextToken();
return cin.sval;
}
public static void closeAll()
{
cout.close();
}
}
解法2(优化暴力)
加了对每一位的检查,不是203中任意一个数字的话,这个数字毫无意义
public static void main(String[] args) throws IOException
{
StringBuilder str=new StringBuilder();
for(int i=1;i<=2023;i++)
{
char[] s=Integer.toString(i).toCharArray();
for(char t:s)
{
if(t=='2'||t=='0'||t=='3') str.append(t);
}
}
long ans=0;
for(int i=0;i<str.length();i++)
{
if(str.charAt(i)!='2') continue;
for(int j=i+1;j<str.length();j++)
{
if(str.charAt(j)!='0') continue;
for(int k=j+1;k<str.length();k++)
{
if(str.charAt(k)!='2') continue;
for(int l=k+1;l<str.length();l++)
{
if(str.charAt(l)!='3') continue;
ans++;
}
}
}
}
cout.println(ans);
cout.flush();
}
解法3(子序列计数dp)
定义状态
令f[k]表示当前已经扫描到某个位置,恰好匹配到模式串“2023”的前k个字符的子序列数。
f[0]:已经匹配了空串的方案数(也就是我们用它来启动新的匹配)。f[1]:已经匹配了"2"的方案数。f[2]:已经匹配了"20"的方案数。f[3]:已经匹配了"202"的方案数。f[4]:已经匹配了"2023"的方案数(最终答案)。状态转移
每读到一个字符c,如果它等于模式串中的某个位置k的字符,就把之前匹配到前面k个字符的方案数累加到f[k+1]上。if (c == '2') { // 新起一个“2”,同时所有已经匹配过 "20" 的都可接下一个 '2' f[1] += f[0]; f[3] += f[2]; } else if (c == '0') { // 所有已经匹配过 '2' 的都可接 '0' f[2] += f[1]; } else if (c == '3') { // 所有已经匹配过 "202" 的都可接 '3' f[4] += f[3]; }
双子数(埃氏筛,注意int和long最大值)

埃氏筛+枚举,注意枚举的时候p*p*q*q可能会爆long
package lqb;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.StreamTokenizer;
import java.util.ArrayList;
public class Main {
// public static StreamTokenizer cin=new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
// public static PrintWriter cout=new PrintWriter(new OutputStreamWriter(System.out));
static StreamTokenizer cin=new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
static PrintWriter cout=new PrintWriter(new OutputStreamWriter(System.out));
static BufferedReader bf=new BufferedReader(new InputStreamReader(System.in));
public static void main(String[] args) throws IOException
{
long ans=0;
long L=2333,R=23333333333333L;
int M=(int)Math.sqrt(R/4);
ArrayList<Integer> prime=new ArrayList<Integer>();
boolean[] vis=new boolean[M+1];
for(int i=2;i<=M;i++)
{
if(!vis[i])
{
prime.add(i);
for(long j=1L*i*i;j<=M;j+=i)
{
vis[(int)j]=true;
}
}
}
for(int i=0;i<prime.size();i++)
{
long p=prime.get(i);
for(int j=i+1;j<prime.size();j++)
{
long q=prime.get(j);
long ppq=p*p*q; //注意这里直接用ppqq,long可能溢出,所以要
long ppqq=ppq*q;
if(ppq>R||ppqq>R) break;
if(ppqq>=L) ans++;
}
}
cout.print(ans);
cout.flush();
}
public static int nextInt() throws IOException {
cin.nextToken();
return (int)cin.nval;
}
public static long nextLong() throws IOException {
cin.nextToken();
return (long)cin.nval;
}
public static double nextDouble() throws IOException {
cin.nextToken();
return cin.nval;
}
public static String nextString() throws IOException {
cin.nextToken();
return cin.sval;
}
public static void closeAll()
{
cout.close();
}
}
- 注意在算的时候有没有可能超过int或long的最大值
班级活动(思维,读题)

package lqb;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.StreamTokenizer;
import java.util.Arrays;
import java.util.HashMap;
public class Main {
// static StreamTokenizer cin=new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
// static PrintWriter cout=new PrintWriter(new OutputStreamWriter(System.out));
// static BufferedReader bf=new BufferedReader(new InputStreamReader(System.in));
static StreamTokenizer cin=new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
static PrintWriter cout=new PrintWriter(new OutputStreamWriter(System.out));
static BufferedReader bf=new BufferedReader(new InputStreamReader(System.in));
static int N=100005,n;
static int[] a;
public static void main(String[] args) throws IOException
{
n=nextInt();
a=new int[n];
Arrays.fill(a, 0);
HashMap<Integer,Integer> map=new HashMap<Integer, Integer>();
for(int i=0;i<n;i++)
{
int t=nextInt();
map.put(t,map.getOrDefault(t, 0)+1);
}
int ans=0;
int x=0,y=0;
for(int a:map.values())
{
if(a>2) x+=a-2;
else if(a<2) y+=a;
}
if(x>=y) ans=x;
else ans=x+(y-x)/2;
cout.println(ans);
cout.flush();
}
public static int nextInt() throws IOException {
cin.nextToken();
return (int)cin.nval;
}
public static long nextLong() throws IOException {
cin.nextToken();
return (long)cin.nval;
}
public static double nextDouble() throws IOException {
cin.nextToken();
return cin.nval;
}
public static String nextString() throws IOException {
cin.nextToken();
return cin.sval;
}
public static void closeAll()
{
cout.close();
}
}
合并数列(思维,双指针)
首先注意这个题目只要求操作次数就行
当两个数不相同的时候,只能向后合并,因为前面的已经合并完了。
合并数可以不用非得把那些数合并,可以用cnt来表示那个区间的数之和来替代合并的数。
如果cnt1<cnt2,则a数组的那个数需要向后合并一个数。cnt1>cnt2反之。
在向后合并的时候记一下数,那个数就是答案,
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.StreamTokenizer;
public class Main {
// static StreamTokenizer cin=new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
// static PrintWriter cout=new PrintWriter(new OutputStreamWriter(System.out));
// static BufferedReader bf=new BufferedReader(new InputStreamReader(System.in));
static StreamTokenizer cin=new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
static PrintWriter cout=new PrintWriter(new OutputStreamWriter(System.out));
static BufferedReader bf=new BufferedReader(new InputStreamReader(System.in));
static int N=100005,n,m;
public static void main(String[] args) throws IOException
{
n=nextInt();m=nextInt();
int[] a=new int[n+2];
int[] b=new int[m+2];
for(int i=1;i<=n;i++) a[i]=nextInt();
for(int j=1;j<=m;j++) b[j]=nextInt();
int cnt1=0,cnt2=0;
int u=0,v=0;
int ans=0;
while(u<=n&&v<=m)
{
if(cnt1==cnt2)
{
cnt1=a[++u];
cnt2=b[++v];
}
else if(cnt1>cnt2)
{
cnt2+=b[++v];
ans++;
}
else
{
cnt1+=a[++u];
ans++;
}
}
cout.println(ans);
cout.flush();
}
public static int nextInt() throws IOException {
cin.nextToken();
return (int)cin.nval;
}
public static long nextLong() throws IOException {
cin.nextToken();
return (long)cin.nval;
}
public static double nextDouble() throws IOException {
cin.nextToken();
return cin.nval;
}
public static String nextString() throws IOException {
cin.nextToken();
return cin.sval;
}
public static void closeAll()
{
cout.close();
}
}
- 看清题目要求什么,有时候一些比较难求的东西可以不用求,只要求题目要的答案就行
数三角(几何)

由于数据量比较小,可以先对每个点求出和其他点的距离,放到数组里,方便后面查询
求出来之后,对于每个点都当做顶点来循环,找到两个和它距离一样的点后答案数加1
这里还需要注意共线问题,这里用向量来判断
import java.io.*;
import java.util.Arrays;
import java.util.HashMap;
import java.util.PriorityQueue;
public class Main {
static StreamTokenizer cin=new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
static PrintWriter cout=new PrintWriter(new OutputStreamWriter(System.out));
static BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
static class Point{
double x,y;
double[] dis=new double[N];
public Point(double x, double y) {
this.x = x;
this.y = y;
}
}
static double distance(Point a,Point b)
{
double disx=a.x-b.x;
double disy=a.y-b.y;
return Math.sqrt(disx*disx+disy*disy);
}
static boolean check(Point p1,Point p2,Point p3)
{
double dx1=p2.x-p1.x,dx2=p3.x-p2.x;
double dy1=p2.y-p1.y,dy2=p3.y-p2.y;
if(dx1*dy2==dx2*dy1) return false;
return true;
}
static int INF=0x3f3f3f3f,N=2005,n;
static Point[] points;
public static void main(String[] args) throws IOException {
n=nextInt();
points=new Point[n+2];
for (int i = 0; i < n; i++) {
double x=nextInt(),y=nextInt();
points[i]=new Point(x,y);
}
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
if(j==i) points[i].dis[j]=0;
else points[i].dis[j]=distance(points[i],points[j]);
}
}
// for (int i = 0; i < n; i++) {
// cout.print((i+1)+": ");
// for (int j = 0; j < n; j++) {
// cout.print(points[i].dis[j]+" ");
// }
// cout.println();
// }
int ans=0;
for(int i=0;i<n;i++)
{
Point p=points[i];
for(int j=0;j<n;j++)
for(int k=j+1;k<n;k++)
{
if(p.dis[j]==p.dis[k]&&check(points[i],points[j],points[k]))
{
// cout.println((i+1)+" "+(j+1)+" "+(k+1));
ans++;
}
}
}
cout.println(ans);
cout.flush();
}
static int nextInt() throws IOException {
cin.nextToken();
return (int)cin.nval;
}
static double nextDouble() throws IOException {
cin.nextToken();
return cin.nval;
}
static long nextLong() throws IOException {
cin.nextToken();
return (long) cin.nval;
}
}
- 判断共线可以用
dx1*dy2==dx2*dy1来判断,如果成立则共线。
删边问题(不会tarjan)
AB路线(BFS)

这里一开始用dfs做的,但是做不出来。
注意这里只要求最短路步数就行,所以用bfs求最短路,直接可以得到步数。
但是要注意对于每个点的状态的定义
import java.io.*;
import java.util.*;
public class Main {
static StreamTokenizer cin=new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
static PrintWriter cout=new PrintWriter(new OutputStreamWriter(System.out));
static BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
static class Pair{
int x,y,flag;
public Pair(int x, int y, int flag) {
this.x = x;
this.y = y;
this.flag = flag;
}
}
static int INF=0x3f3f3f3f,N=1005,n,m,k;
static int[][][] f;
static int[] dx={0,0,1,-1},dy={1,-1,0,0};
static char[][] map=new char[N][N];
static boolean check(int x,int y)
{
return x<n&&x>=0&&y<m&&y>=0;
}
public static void main(String[] args) throws IOException {
n=nextInt();m=nextInt();k=nextInt();
f=new int[n+2][m+2][k+2];
map=new char[n+2][m+2];
for(int i=0;i<n;i++)
{
String t=nextString();
map[i]=t.toCharArray();
}
Queue<Pair> qu=new ArrayDeque<>();
qu.offer(new Pair(0,0,1));
int[][] d={{0,1},{0,-1},{1,0},{-1,0}};
boolean[][][] vis=new boolean[n][m][2*k];
for(int step=0;!qu.isEmpty();step++)
{
int num= qu.size();
for(int i=0;i<num;i++)
{
Pair pair=qu.poll();
int px=pair.x,py=pair.y,pf=pair.flag;
if(vis[px][py][pf]) continue;
vis[px][py][pf]=true;
if(pair.x==n-1&&pair.y==m-1)
{
cout.println(step);
cout.flush();
return;
}
for(int j=0;j<4;j++)
{
int x=px+d[j][0];
int y=py+d[j][1];
int f=(pf+1)%(2*k);
if(check(x,y))
{
if(vis[x][y][f]) continue;
if(pf<k&&map[x][y]=='A'||pf>=k&&map[x][y]=='B')
{
qu.offer(new Pair(x,y,f));
}
}
}
}
}
// for(int i=0;i<n;i++)
// {
// for(int j=m-1;j>=0;j--)
// {
// map[i][j]=map[i][j-1];
// }
// }
cout.println(-1);
cout.flush();
}
static int nextInt() throws IOException {
cin.nextToken();
return (int)cin.nval;
}
static double nextDouble() throws IOException {
cin.nextToken();
return cin.nval;
}
static long nextLong() throws IOException {
cin.nextToken();
return (long) cin.nval;
}
static String nextString() throws IOException {
cin.nextToken();
return cin.sval;
}
}
抓娃娃(前缀和差分判断区间点的数量)

这里只需要判断线段的中点是否在区间之内就能判断是否符合。同时这里只需要判断数量即可,所以可以利用前缀和,求0~i之内的中点的数量,sum[i],然后用区间进行差分sum[L]-sum[R-1],即可得到区间的数量。
需要注意这里由于是求中点,所以会有小数的情况,我们把所有区间都乘2就不会有小数了
import java.io.*;
import java.util.*;
public class Main {
static StreamTokenizer cin=new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
static PrintWriter cout=new PrintWriter(new OutputStreamWriter(System.out));
static BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
static class Range{
double l,r;
double mid;
public Range(double l, double r) {
this.l = l;
this.r = r;
this.mid=(l+r)/2;
}
}
static boolean check(Range o,Range O)//o是否在O里面
{
if(o.l<O.l&&o.mid>=O.l) return true;
if(o.l>=O.l&&o.r<=O.r) return true;
if(o.r>O.r&&o.mid<=O.r) return true;
return false;
}
static int n,m,N=1000005;
static int[] sum=new int[2*N];
static Range[] r1,r2;
public static void main(String[] args) throws IOException {
n=nextInt();m=nextInt();
for(int i=0;i<n;i++)
{
int l=nextInt(),r=nextInt();
sum[l+r]++;
}
for(int i=1;i<N*2;i++) sum[i]+=sum[i-1];
for(int i=0;i<m;i++)
{
int L=nextInt(),R=nextInt();
cout.println(sum[2*R]-sum[2*L-1]);
}
cout.flush();
}
static int nextInt() throws IOException {
cin.nextToken();
return (int)cin.nval;
}
static double nextDouble() throws IOException {
cin.nextToken();
return cin.nval;
}
static long nextLong() throws IOException {
cin.nextToken();
return (long) cin.nval;
}
static String nextString() throws IOException {
cin.nextToken();
return cin.sval;
}
}
- 求区间中点的数量可以用前缀和处理,然后用差分得到答案
拼数字(不会,跳)
逃跑(不会,跳)
14届python B
弹珠堆放(暴力)

每一层的个数是\(1+2+3+...+n=(n+1)n/2\)
import java.io.*;
import java.util.*;
public class Main {
static StreamTokenizer cin=new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
static PrintWriter cout=new PrintWriter(new OutputStreamWriter(System.out));
static BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
public static void main(String[] args) throws IOException {
int cnt=0;
int i=1;
while(true)
{
cnt+=(i+1)*i/2;
cout.println(i+":"+cnt);
if(cnt>20230610) break;
i++;
}
cout.println(i-1);
cout.flush();
}
static int nextInt() throws IOException {
cin.nextToken();
return (int)cin.nval;
}
static double nextDouble() throws IOException {
cin.nextToken();
return cin.nval;
}
static long nextLong() throws IOException {
cin.nextToken();
return (long) cin.nval;
}
static String nextString() throws IOException {
cin.nextToken();
return cin.sval;
}
}
划分(01背包划分集合尽量相等)

由基本不等式可以知道,两个数如果相等的话是最大值。那么就求这个集合里最相近的两个数就行了。
在背包问题中求dp[i][j]时,得到的是离j最近的数,所以可以用01背包求小于sum/2的值,另外一个大于sum/2的值就得到了,相乘就是答案。
import java.io.*;
import java.util.*;
public class Main {
static StreamTokenizer cin=new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
static PrintWriter cout=new PrintWriter(new OutputStreamWriter(System.out));
static BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
public static void main(String[] args) throws IOException {
// int[] arr={
// 5160,9191,6410,4657,7492,1531,8854,1253,4520,9231,
// 1266,4801,3484,4323,5070 ,1789 ,2744 ,5959,9426 ,4433,
// 4404, 5291, 2470 ,8533, 7608 ,2935 ,8922 ,5273 ,8364, 8819,
// 7374, 8077 ,5336 ,8495 ,5602 ,6553 ,3548 ,5267 ,9150 ,3309};
// int sum=226924;
//
// long[] dp=new long[sum+1];
// for(int i=0;i<arr.length;i++)
// for(int j=sum;j>=arr[i];j--)
// dp[j]=Math.max(dp[j],dp[j-arr[i]]+arr[i]);
// cout.println(dp[sum/2]*(sum-dp[sum/2]));
// System.out.println();
// cout.flush();
System.out.println(12873625444L);
}
static int nextInt() throws IOException {
cin.nextToken();
return (int)cin.nval;
}
static double nextDouble() throws IOException {
cin.nextToken();
return cin.nval;
}
static long nextLong() throws IOException {
cin.nextToken();
return (long) cin.nval;
}
static String nextString() throws IOException {
cin.nextToken();
return cin.sval;
}
}
偶串(哈希表)

直接用哈希表记录字符串和出现的次数就行
import java.io.*;
import java.util.*;
public class Main {
static StreamTokenizer cin=new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
static PrintWriter cout=new PrintWriter(new OutputStreamWriter(System.out));
static BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
public static void main(String[] args) throws IOException {
HashMap<Character,Integer> hash=new HashMap<>();
char[] str=nextString().toCharArray();
for(char t:str)
{
hash.put(t,hash.getOrDefault(t,0)+1);
}
boolean flag=false;
for(Integer t:hash.values())
{
if(t%2!=0) flag=true;
}
if(flag) cout.println("NO");
else cout.println("YES");
cout.flush();
}
static int nextInt() throws IOException {
cin.nextToken();
return (int)cin.nval;
}
static double nextDouble() throws IOException {
cin.nextToken();
return cin.nval;
}
static long nextLong() throws IOException {
cin.nextToken();
return (long) cin.nval;
}
static String nextString() throws IOException {
cin.nextToken();
return cin.sval;
}
}
-------------------------
15届JAVA B
类斐波那契循环数(把数变成字符串再取每一位。用栈记录总合中的数字组成)
import java.util.*;
public class Main {
static int N = 1100, INF = 0x3f3f3f3f;
public static int sumDigits(int[] arr)
{
int sum=0;
for(int num:arr)
{
sum+=num;
}
return sum;
}
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
// int n=scan.nextInt();
for (int i = (int)1e7; i>0; i--) {
// System.out.println(i);
String str=Integer.toString(i);
int size=str.length();
int[] num = new int[size];
for(int j=0;j<size;j++)
{
num[j]=str.charAt(j)-'0';
// System.out.println(num[j]);
}
int sum = 0;
Deque<Integer> queue=new ArrayDeque<>();
for(int d:num)
{
// System.out.println(d);
queue.addLast(d);
}
sum=sumDigits(num);
if(sum==i)
{
System.out.println(i);
return;
}
if(sum>i)
{
break;
}
while (true)
{
int next=sum;
if(queue.size()>=size)
{
sum-=queue.removeFirst();
}
queue.addLast(next);
sum+=next;
if(sum==i){
System.out.println(i);
return;
}
if(sum>i)
{
break;
}
}
}
}
}
- 用
Integer.toString(i);和str.charAt(j)-'0';来正着取一个数的每一位 - 队列
Deque<Integer> queue=new ArrayDeque<>();
分布式队列(模拟,但是有的地方不需要模拟)

import java.util.*;
public class Main {
static int N = 105, INF = 0x3f3f3f3f;
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
int n=scan.nextInt();
// int[][] node=new int[n][N];
int[] station=new int[n];
int minst=0;
String cmd= "";
while (scan.hasNext())
{
cmd=scan.next();
if(cmd.equals("add"))
{
// System.out.println("add");
int element=scan.nextInt();
// System.out.println(element);
// node[0][station[0]]=element;
station[0]++;
}
if(cmd.equals("sync"))
{
int follower=scan.nextInt();
if(station[follower]<station[0])
{
// node[follower][station[follower]]=node[follower][station[follower]];
station[follower]++;
}
}
if(cmd.equals("query"))
{
minst=station[0];
for(int i=1;i<n;i++)
{
minst=Math.min(station[i],minst);
}
System.out.println(minst);
}
}
}
}
- 模拟的时候可以不用全部模拟,看答案需求,有的地方不需要模拟也可以输出正确答案
- 用
scan.hasNext()来表示有没有下一个输入
食堂(大模拟,分类讨论。用while循环一个一个检查,不要除和取余直接求)

import java.util.*;
public class Main {
static int N = 105, INF = 0x3f3f3f3f;
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
int q=scan.nextInt();
while ((q--)!=0)
{
int a2,a3,a4,b4,b6,sum=0;
a2=scan.nextInt();
a3=scan.nextInt();
a4=scan.nextInt();
b4=scan.nextInt();
b6=scan.nextInt();
while(a4*4>=4&&b4>0)//4*1=4
{
a4-=1;b4-=1;sum+=4;
}
while(a2*2>=4&&b4>0) //2*2=4
{
a2-=2;b4-=1;sum+=4;
}
while (a2*2>=2&&a4*4>=4&&b6>0)//2+4=6
{
a2-=1;a4-=1;b6-=1;sum+=6;
}
while (a2*2>=6&&b6>0)//2*3=6
{
a2-=3;b6-=1;sum+=6;
}
while(a3*3>=6&&b6>0)//3*2=6
{
a3-=2;b6-=1;sum+=6;
}
while (a3*3>=3&&b4>0)//余1:3=3
{
a3-=1;b4-=1;sum+=3;
}
while (a3*3>=3&&a2*2>=2&&b6>0)//余1:2+3=5
{
a3-=1;a2-=1;b6-=1;sum+=5;
}
while (a4*4>=4&&b6>0)//余2:4=4
{
a4-=1;b6-=1;sum+=4;
}
while (a2*2>=4&&b6>0)//余2:2*2=4
{
a2-=2;b6-=1;sum+=4;
}
while (a2*2>=2&&b4>0)//余2:2=2
{
a2-=1;b4-=1;sum+=2;
}
while (a3*3>=3&&b6>0)//余3:3=3
{
a3-=1;b6-=1;sum+=3;
}
while (a2*2>=2&&b6>0)//余4:2=2
{
a2-=1;b6-=1;sum+=2;
}
// System.out.println(a2+" "+a3+" "+a4+" "+b4+" "+b6+" ");
// sum+=(b4*4+b6*6);
System.out.println(sum);
}
}
}
- 枚举的时候不要用
/和%来枚举,不要一口气完成。用while循环来枚举 - 分类讨论的时候按顺序来,不要怕这种大模拟
- 这题优先枚举4人桌,再枚举6人桌。先枚举整个的,再枚举缺的
- 这题的答案是在满足条件的情况下尽可能多的人在食堂,不能超过总人数
最优分组(高中生物)

一组K只宠物,那么没有宠物感染的概率就是P=(1-p)^K,至少有一只宠物感染的概率即1-P,对于对于一共N/K组,自然即有P*N/K组未感染,(1-P)*N/K组感染,未感染的话只需1只药剂,否则需要(1+K)支药剂(K==1时除外)(官解的公式里写成1*K了,但是代码是对的,结果我看半天不知道为什么),那么用药数量就是E=(P+(1-P)(K+1))N/K了,对于N是否能正好分成K份,因为数据小直接暴力就完事
import java.util.*;
public class Main {
static int N = 105, INF = 0x3f3f3f3f;
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
int n= scan.nextInt();
double p=scan.nextDouble();
int minK=Integer.MAX_VALUE;
double minE=Double.MAX_VALUE;
for(int K=n;K>=1;K--)
{
if(n%K==0)
{
double P=Math.pow(1-p,K);
double E=(P+(1-P)*(K+1))*N/K;
if(K==1) K=N;
if(E<minE)
{
minK=K;
minE=E;
}
}
}
System.out.println(minK);
}
}
- 碰到实际的问题也可以实际上去想,这里就用到了高中生物概率题里的常见思维
- 需要注意这题
K=1的时候K=N,不能套用公式,因为这个时候公式为0。
星际旅行(folyd求最短路)

import java.util.*;
public class Main {
static int N=220,INF=0x3f3f3f3f,n,m,q,sum;
// static int[][] g=new int[N][N];
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
n= scan.nextInt();
m= scan.nextInt();
q= scan.nextInt();
int[][] g=new int[n+1][n+1];
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
{
if(i==j) g[i][j]=0;
else g[i][j]=INF;
// g[i][j]=INF;
}
while (m-- > 0)
{
int a= scan.nextInt();
int b=scan.nextInt();
g[a][b]=g[b][a]=1;
}
for(int k=1;k<=n;k++)
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
g[i][j]=Math.min(g[i][j],g[i][k]+g[k][j]);
int t=q;
while (t-- > 0)
{
int x= scan.nextInt();
int y=scan.nextInt();
for(int i=1;i<=n;i++)
{
if(g[x][i]<=y) sum++;
}
}
System.out.printf("%.2f",(double)sum/q);
}
}
- java中可以不用一开始就新建数组,可以在得到数组长度后再新建
- 要看清输出格式的要求,是整数还是浮点数,要保留几位小数
- java中的如果要保留两位小数就要用
System.out.printf("%.2f",(double)sum/q);
LITS游戏(程序画图枚举)

import java.util.*;
public class Main {
static int[][][][] pl={
{
{{0,0},{1,0},{2,0},{2,1}}, //0
{{0,0},{1,0},{0,1},{0,2}},//90
{{0,0},{0,1},{1,1},{2,1}},//180
{{1,0},{1,1},{1,2},{0,2}}//270
},
{
{{0,0},{1,0},{2,0},{3,0}},
{{0,0},{0,1},{0,2},{0,3}}
},
{
{{0,0},{0,1},{0,2},{1,1}},//0
{{1,0},{0,1},{1,1},{2,2}},//90
{{1,0},{1,1},{0,1},{1,2}},//180
{{0,0},{1,0},{2,0},{1,1}}//270
},
{
{{1,0},{0,1},{1,1},{0,2}},
{{0,0},{1,0},{1,1},{2,1}}
}
};
static int N=55,INF=0x3f3f3f3f,t,n;
static int[][] g=new int[N][N];
static boolean success;
static boolean inBound(int x,int y)
{
return x>=1&&x<=n&&y>=1&&y<=n;
}
static boolean canPlace(int type,int chosen,int startX,int startY)
{
for(int[] pos:pl[type][chosen]){
int x=startX+pos[0],y=startY+pos[1];
if(!inBound(x,y)||g[x][y]!=1) return false;
}
return true;
}
static void draw(int type,int chosen,int startX,int startY,int target)
{
for(int[] pos:pl[type][chosen]) g[startX+pos[0]][startY+pos[1]]=target;
}
static void choosePlan(int now)
{
if(success) return;
if(now==4) success=true;
else for(int i=0;i<pl[now].length;i++)
{
if(success) return;
for(int x=1;x<=n;x++)
{
for(int y=1;y<=n;y++)
{
if(!canPlace(now,i,x,y)) continue;
draw(now,i,x,y,2);
choosePlan(now+1);
draw(now,i,x,y,1);
}
}
}
}
static boolean solve(){
success=false;
choosePlan(0);
return success;
}
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
t=scan.nextInt();
while (t-- > 0)
{
n=scan.nextInt();
// success=false;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
g[i][j]=scan.nextInt();
}
}
System.out.println(solve()?"Yes":"No");
}
}
}
- 通过枚举每个位置上的图形来得到答案
15届pythonB
连连看(几何特征减少复杂度)

暴力代码:过50%
import java.io.*;
import java.math.BigDecimal;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Scanner;
public class Main {
public static StreamTokenizer cin=new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
public static PrintWriter cout=new PrintWriter(new OutputStreamWriter(System.out));
static int N=(int)1e3+4,n,m,ans;
static int[][] g=new int[N][N];
public static void main(String[] args) throws IOException {
n=nextInt();m=nextInt();
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
g[i][j]=nextInt();
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
for(int k=1;k<=n;k++)
for(int l=1;l<=m;l++)
if(i!=k && j!=l && g[i][j]==g[k][l] && Math.abs(i-k)==Math.abs(j-l) && Math.abs(i-k)>0)
ans++;
cout.println(ans);
cout.flush();
}
public static int nextInt() throws IOException {
cin.nextToken();
return (int)cin.nval;
}
public static long nextLong() throws IOException {
cin.nextToken();
return (long)cin.nval;
}
public static double nextDouble() throws IOException {
cin.nextToken();
return cin.nval;
}
public static String nextString() throws IOException {
cin.nextToken();
return cin.sval;
}
public static void closeAll()
{
cout.close();
}
}
通过几何特征:如果要满足|a-c|=|b-d|>0,那么只有右上45度,右下45度,左上45度,左下45度符合要求。可以将复杂度减少到O(n^3)
import java.io.*;
import java.math.BigDecimal;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Scanner;
public class Main {
public static StreamTokenizer cin=new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
public static PrintWriter cout=new PrintWriter(new OutputStreamWriter(System.out));
static int N=(int)1e3+4,n,m,ans;
static int[][] g=new int[N][N];
// static int check(int )
static boolean check(int x,int y)
{
return x>=1&&x<=n&&y>=1&&y<=m;
}
public static void main(String[] args) throws IOException {
n=nextInt();m=nextInt();
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
g[i][j]=nextInt();
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
{
for(int k=1;check(i-k,j+k);k++) //右上
{
if(g[i][j]==g[i-k][j+k]) ans++;
}
for(int k=1;check(i+k,j+k);k++) //右下
{
if(g[i][j]==g[i+k][j+k]) ans++;
}
for(int k=1;check(i-k,j-k);k++) //左上
{
if(g[i][j]==g[i-k][j-k]) ans++;
}
for(int k=1;check(i+k,j-k);k++) //左下
{
if(g[i][j]==g[i+k][j-k]) ans++;
}
}
// for(int i=1;i<=n;i++)
// for(int j=1;j<=m;j++)
// for(int k=1;k<=n;k++)
// for(int l=1;l<=m;l++)
// if(i!=k && j!=l && g[i][j]==g[k][l] && Math.abs(i-k)==Math.abs(j-l) && Math.abs(i-k)>0)
// ans++;
cout.println(ans);
cout.flush();
}
public static int nextInt() throws IOException {
cin.nextToken();
return (int)cin.nval;
}
public static long nextLong() throws IOException {
cin.nextToken();
return (long)cin.nval;
}
public static double nextDouble() throws IOException {
cin.nextToken();
return cin.nval;
}
public static String nextString() throws IOException {
cin.nextToken();
return cin.sval;
}
public static void closeAll()
{
cout.close();
}
}
- 有一些题可以通过找一些几何特性来减少复杂度
神奇闹钟(日期问题)
蓝桥村的真相(思维,枚举找规律)


这里用暴力的做法来做(过不了几个)
import java.io.*;
import java.math.BigDecimal;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Scanner;
public class Main {
public static StreamTokenizer cin=new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
public static PrintWriter cout=new PrintWriter(new OutputStreamWriter(System.out));
static int N=(int)1e5+4,T,ans;
static int[] st=new int[N];
static void dfs(boolean[] g,int idx,int n)
{
if(idx==n)
{
// for(int i=0;i<n;i++) cout.print(g[i]+" ");
// cout.println();
boolean flag=true;
int cnt=0;
for(int i=0;i<n;i++)
{
if(g[i]&&g[(i+1)%n]==g[(i+2)%n]) flag=false;
if(!g[i]&&g[(i+1)%n]!=g[(i+2)%n]) flag=false;
if(!flag) break;
if(!g[i]) cnt++;
}
if(flag)
{
ans+=cnt;
// cout.println("--------------------");
}
else
{
return;
}
}
if(idx<n)
{
g[idx]=true;
dfs(g,idx+1,n);
g[idx]=false;
dfs(g,idx+1,n);
}
}
public static void main(String[] args) throws IOException {
// int n=nextInt();
boolean flag=true;
for(int i=1;i<=50;i++)
{
ans=0;
dfs(new boolean[i+1],0,i);
cout.println(i+" "+ans);
cout.flush();
}
}
public static int nextInt() throws IOException {
cin.nextToken();
return (int)cin.nval;
}
public static long nextLong() throws IOException {
cin.nextToken();
return (long)cin.nval;
}
public static double nextDouble() throws IOException {
cin.nextToken();
return cin.nval;
}
public static String nextString() throws IOException {
cin.nextToken();
return cin.sval;
}
public static void closeAll()
{
cout.close();
}
}
- 暴力:对于这种一个数组里面的数的排列组合可以用dfs来枚举,一开始没想到dfs
- 如果是真,那么后面两个不一样。如果是假,那么后面两个一样。一开始没想到
- 对于一些题可以通过枚举来看能不能找到规律
魔法巡游20%(暴力模拟)



import java.io.*;
import java.math.BigDecimal;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Scanner;
public class Main {
public static StreamTokenizer cin=new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
public static PrintWriter cout=new PrintWriter(new OutputStreamWriter(System.out));
static int N=(int)1e5+4,n,ans;
static int[] s=new int[N],t=new int[N];
static int check(int x) //用二进制表示是否有0,2,4。
{
int ans=0;
while (x!=0)
{
int t=x%10;
if(t==0&&(ans&1)==0) ans+=1;
if(t==2&&(ans&2)==0) ans+=2;
if(t==4&&((ans&4)==0)) ans+=4;
x/=10;
}
return ans;
}
public static void main(String[] args) throws IOException {
n=nextInt();
for(int i=1;i<=n;i++)
{
s[i]=check(nextInt());
cout.print(Integer.toBinaryString(s[i])+" ");
}
cout.println();
for(int i=1;i<=n;i++)
{
t[i]=check(nextInt());
cout.print(Integer.toBinaryString(t[i])+" ");
}
cout.println();
boolean flag=false;//true表示下一个是小蓝,false表示下一个是小桥
int x,last;
for(x=1;s[x]==0&&x<=n;x++);//小蓝先走
cout.println(x+" "+Integer.toBinaryString(s[x]));
last=s[x];x++;ans++;
while (x<=n)
{
if(flag)
{
while (x<=n&&(last&s[x])==0) x++;
if(x>n) break;
cout.println(x+" "+Integer.toBinaryString(s[x]));
last=s[x];ans++;x++;
flag=false;
}
else
{
while (x<=n&&(last&t[x])==0) x++;
if(x>n) break;
cout.println(x+" "+Integer.toBinaryString(t[x]));
last=t[x];ans++;x++;
flag=true;
}
}
cout.println(ans);
cout.flush();
}
public static int nextInt() throws IOException {
cin.nextToken();
return (int)cin.nval;
}
public static long nextLong() throws IOException {
cin.nextToken();
return (long)cin.nval;
}
public static double nextDouble() throws IOException {
cin.nextToken();
return cin.nval;
}
public static String nextString() throws IOException {
cin.nextToken();
return cin.sval;
}
public static void closeAll()
{
cout.close();
}
}
- 这题因为审题被坑了,一开始以为不用两个一样的就可以。在做题前要仔细审查每一个情况
纯职业小组(不会)
15届C B
数字接龙(dfs)


import java.io.*;
import java.math.BigDecimal;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Scanner;
public class Main {
public static StreamTokenizer cin=new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
public static PrintWriter cout=new PrintWriter(new OutputStreamWriter(System.out));
static int N=12,cnt,n,k;
static int[][] g=new int[N][N];
static int[] dx={-1,-1,0,1,1,1,0,-1},dy={0,1,1,1,0,-1,-1,-1};
static int[] ans=new int[102],ans1=new int[102];
static boolean[][] st=new boolean[N][N];
static boolean[][][][] edge=new boolean[N][N][N][N];
static boolean check(int x,int y)
{
return x>=0&&x<n&&y>=0&&y<n&&!st[x][y];
}
static void dfs(int x,int y,int idx)
{
if(x==n-1&&y==n-1&&idx==cnt)
{
// for(int i=0;i<cnt;i++) cout.print(ans1[i]);
// cout.println();
boolean flag=false;
for(int i=0;i<cnt;i++)
{
if(ans1[i]<ans[i])
{
flag=true;
break;
}
if(ans1[i]>ans[i]) break;
}
if(flag)
{
for(int i=0;i<cnt;i++) ans[i]=ans1[i];
}
}
for(int i=0;i<8;i++)
{
int nx=x+dx[i],ny=y+dy[i];
if(check(nx,ny)&&(g[x][y]+1)%k==g[nx][ny])
{
if(i%2==1&&(edge[nx][y][x][ny]||edge[x][ny][nx][y])) continue;
if(i%2==1) edge[x][y][nx][ny]=true;
ans1[idx]=i;st[nx][ny]=true;
dfs(nx,ny,idx+1);
if(i%2==1) edge[x][y][nx][ny]=false;
ans1[idx]=0;st[nx][ny]=false;
}
}
}
public static void main(String[] args) throws IOException {
n=nextInt();
k=nextInt();
cnt=n*n-1;
st[0][0]=true;
for(int i=0;i<cnt;i++) ans[i]=9;
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
g[i][j]=nextInt();
dfs(0,0,0);
for(int i=0;i<cnt;i++) cout.print(ans[i]);
cout.flush();
}
public static int nextInt() throws IOException {
cin.nextToken();
return (int)cin.nval;
}
public static long nextLong() throws IOException {
cin.nextToken();
return (long)cin.nval;
}
public static double nextDouble() throws IOException {
cin.nextToken();
return cin.nval;
}
public static String nextString() throws IOException {
cin.nextToken();
return cin.sval;
}
public static void closeAll()
{
cout.close();
}
}
- 没想到用
edge[][][][]表示斜走有没有交叉,其他倒是都想到了
14届C B
日期统计(子序列,暴力)

package lqb;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.StreamTokenizer;
public class Main {
// public static StreamTokenizer cin=new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
// public static PrintWriter cout=new PrintWriter(new OutputStreamWriter(System.out));
static StreamTokenizer cin=new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
static PrintWriter cout=new PrintWriter(new OutputStreamWriter(System.out));
static int[] num= {5,6,8,6,9,1,6,1,2,4,9,1,9,8,2,3,6,4,7,7,
5,9,5,0,3,8,7,5,8,1,5,8,6,1,8,3,0,3,7,9,2,7,
0,5,8,8,5,7,0,9,9,1,9,4,4,6,8,6,3,3,8,5,1,6,
3,4,6,7,0,7,8,2,7,6,8,9,5,6,5,6,1,4,0,1,0,0,
9,4,8,0,9,1,2,8,5,0,2,5,3,3};
static int[] month_day= {0,31,28,31,30,31,30,31,31,30,31,30,31};
public static void main(String[] args) throws IOException {
int[] date= {0,2,0,2,3,0,0,0,0,0};
int ans=0;
for(int i=1;i<=12;i++)
{
date[5]=i/10;date[6]=i%10;
int day=month_day[i];
for(int j=1;j<=day;j++)
{
date[7]=j/10;date[8]=j%10;
int k=1;
for(int t:num)
{
if(t==date[k]) k++;
if(k>8)
{
ans++;
break;
}
}
}
// for(int j=1;j<=8;j++) cout.print(date[j]);
// cout.println();
// for(int t:num)
// {
// if(t==date[k]) k++;
// if(k>8)
// {
// ans++;
// break;
// }
// }
}
cout.print(ans);
cout.flush();
}
public static int nextInt() throws IOException {
cin.nextToken();
return (int)cin.nval;
}
public static long nextLong() throws IOException {
cin.nextToken();
return (long)cin.nval;
}
public static double nextDouble() throws IOException {
cin.nextToken();
return cin.nval;
}
public static String nextString() throws IOException {
cin.nextToken();
return cin.sval;
}
public static void closeAll()
{
cout.close();
}
}
- 没理解子序列的意思。
子序列是指从一个序列(如数组、字符串等)中按顺序选取若干元素(可以不连续),但保持原始顺序的新序列。
与子串(Substring)不同,子序列不要求元素在原序列中连续。
冶炼金属(数学)


package lqb;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.StreamTokenizer;
public class Main {
// public static StreamTokenizer cin=new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
// public static PrintWriter cout=new PrintWriter(new OutputStreamWriter(System.out));
static StreamTokenizer cin=new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
static PrintWriter cout=new PrintWriter(new OutputStreamWriter(System.out));
public static void main(String[] args) throws IOException {
int n=nextInt();
int min=Integer.MIN_VALUE,max=Integer.MAX_VALUE;
for(int i=0;i<n;i++)
{
int a=nextInt();
int b=nextInt();
min=Math.max(min, (a/(b+1))+1);
max=Math.min(max,(a/b));
}
cout.print(min+" "+max);
cout.flush();
}
public static int nextInt() throws IOException {
cin.nextToken();
return (int)cin.nval;
}
public static long nextLong() throws IOException {
cin.nextToken();
return (long)cin.nval;
}
public static double nextDouble() throws IOException {
cin.nextToken();
return cin.nval;
}
public static String nextString() throws IOException {
cin.nextToken();
return cin.sval;
}
public static void closeAll()
{
cout.close();
}
}
飞机降落(dfs暴力枚举)

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.StreamTokenizer;
public class Main {
// public static StreamTokenizer cin=new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
// public static PrintWriter cout=new PrintWriter(new OutputStreamWriter(System.out));
static StreamTokenizer cin=new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
static PrintWriter cout=new PrintWriter(new OutputStreamWriter(System.out));
static int N=12,n;
static int[][] arr=new int[N][3];//0:T 1:D 2:L
static boolean[] st=new boolean[N];
static boolean flag;
static void dfs(int cnt,int last)
{
if(cnt==n)
{
flag=true;
return;
}
for(int i=0;i<n;i++)
{
if(!st[i]&&arr[i][0]+arr[i][1]>=last)
{
st[i]=true;
dfs(cnt+1,Math.max(arr[i][0],last)+arr[i][2]);
st[i]=false;
}
if(flag) return;
}
}
public static void main(String[] args) throws IOException {
int T=nextInt();
while(T-- > 0)
{
n=nextInt();
flag=false;
for(int i=0;i<n;i++)
{
arr[i][0]=nextInt();
arr[i][1]=nextInt();
arr[i][2]=nextInt();
}
dfs(0,0);
if(flag) cout.println("YES");
else cout.println("NO");
}
cout.flush();
}
public static int nextInt() throws IOException {
cin.nextToken();
return (int)cin.nval;
}
public static long nextLong() throws IOException {
cin.nextToken();
return (long)cin.nval;
}
public static double nextDouble() throws IOException {
cin.nextToken();
return cin.nval;
}
public static String nextString() throws IOException {
cin.nextToken();
return cin.sval;
}
public static void closeAll()
{
cout.close();
}
}
14届JAVA B
阶乘求和

幸运数字

import javax.swing.*;
import java.util.*;
public class Main {
static int N=(int)5e5+4,n,ans;
static boolean check(int x)
{
int sum=0;
String bin=Integer.toBinaryString(x);
String oct=Integer.toOctalString(x);
String ten=Integer.toString(x);
String hex=Integer.toHexString(x);
int[] bins=new int[N],octs=new int[N],tens=new int[N],hexs=new int[N];
for(int i=0;i<bin.length();i++)
{
bins[i]=(int)(bin.charAt(i)-'0');
sum+=bins[i];
}
if(x%sum!=0) return false;
sum=0;
for(int i=0;i<oct.length();i++)
{
octs[i]=(int)(oct.charAt(i)-'0');
sum+=octs[i];
}
if(x%sum!=0) return false;
sum=0;
for(int i=0;i<ten.length();i++)
{
tens[i]=(int)(ten.charAt(i)-'0');
sum+=tens[i];
}
if(x%sum!=0) return false;
sum=0;
for(int i=0;i<hex.length();i++)
{
if(hex.charAt(i)=='a') hexs[i]=10;
else if(hex.charAt(i)=='b') hexs[i]=11;
else if(hex.charAt(i)=='c') hexs[i]=12;
else if(hex.charAt(i)=='d') hexs[i]=13;
else if(hex.charAt(i)=='e') hexs[i]=14;
else if(hex.charAt(i)=='f') hexs[i]=15;
else {
hexs[i]=(int)(hex.charAt(i)-'0');
}
}
for(int i=0;i<hex.length();i++) sum+=hexs[i];
if(x%sum!=0) return false;
return true;
}
public static void main(String[] args) {
Scanner scan=new Scanner(System.in);
n=1;
while (ans!=2023)
{
if(check(n))
{
ans++;
System.out.println(n+" "+ans);
}
n++;
}
System.out.println(n-1);
}
}
- 题目里举例子了一定要用到这个测试集来测试程序
数组分割



import javax.swing.*;
import java.io.*;
import java.util.*;
public class Main {
static int N=(int)1e3+4,MOD=1000000007,t,n;
public static void main(String[] args) throws IOException {
StreamTokenizer cin=new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
PrintWriter cout=new PrintWriter(new OutputStreamWriter(System.out));
cin.nextToken();t=(int)cin.nval;
while (t-- > 0)
{
cin.nextToken();n=(int)cin.nval;
// int[] num=new int[n];
int onum=0;
int snum=0;
int t=0;
int ans=0;
for(int i=1;i<=n;i++)
{
cin.nextToken();t=(int)cin.nval;
if((t&1)==1) onum=(onum+1)%MOD;
else snum=(snum+1)%MOD;
}
if((onum&1)==1)
{
cout.println("0");
cout.flush();
continue;
}
// onum/=2;
// sum=(onum+snum)%MOD;
// cout.println(sum);cout.flush();
if(onum!=0)
{
ans=(int)(Math.pow(2,n-1)%MOD);
cout.println(ans);
cout.flush();
}
else
{
ans=(int)(Math.pow(2,n)%MOD);
cout.println(ans);
cout.flush();
}
}
}
}
- 一开始没理解对,当成了把奇数两个分组,所以出现了
onum/2,但是没想到这样做是强行两两分组,而且不能拆开 - 分清楚是子序列还是子集,一个要求有序,一个无序
矩形总面积(计算几何)

import javax.swing.*;
import java.io.*;
import java.util.*;
public class Main {
public static StreamTokenizer cin=new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
public static PrintWriter cout=new PrintWriter(new OutputStreamWriter(System.out));
// static int x1,x2,y1,y2,x3,x4,y3,y4;
static int ans=0;
public static int Area(int x1,int x2,int y1,int y2)
{
return Math.abs((x1-x2)*(y1-y2));
}
public static void main(String[] args) throws IOException {
int x1,x2,y1,y2,x3,x4,y3,y4;
x1=nextInt();y1=nextInt();x2=nextInt();y2=nextInt();
x3=nextInt();y3=nextInt();x4=nextInt();y4=nextInt();
// int ans=0;
ans=Area(x1,x2,y1,y2)+Area(x3,x4,y3,y4);
int x=Math.abs(Math.min(x2,x4)-Math.max(x1,x3));
int y=Math.abs(Math.min(y2,y4)-Math.max(y1,y3));
if(x>0&&y>0) ans-=x*y;
cout.println(ans);
cout.flush();
}
public static int nextInt() throws IOException {
cin.nextToken();
return (int)cin.nval;
}
public static long nextLong() throws IOException {
cin.nextToken();
return (long)cin.nval;
}
public static double nextDouble() throws IOException {
cin.nextToken();
return cin.nval;
}
public static String nextString() throws IOException {
cin.nextToken();
return cin.sval;
}
public static void closeAll()
{
cout.close();
}
}
- 重叠区域的面积:在x轴上的重叠长度为:
Math.abs(Math.min(x2,x4)-Math.max(x1,x3)),同理,在y轴上重叠长度为Math.abs(Math.min(y2,y4)-Math.max(y1,y3))
蜗牛(简单的动态规划)

-
状态表示
f[i][0],f[i][1]:- 集合:
f[i][0]到达第i个结点的集合。f[i][1]到达第i个传送门的集合 - 属性:min
- 集合:
-
状态计算:
-
`f[i][0]=Math.min(dp(i-1,0)+x[i]-x[i-1],dp(i-1,1)+b[i]/1.3);` `f[i][1]=Math.min(dp(i-1,0)+(x[i]-x[i-1])+a[i]/0.7,dp(i-1,1)+(b[i]>a[i] ? (b[i]-a[i])/1.3 : (a[i]-b[i])/0.7 ));`
-
import java.io.*;
import java.util.*;
public class Main {
public static StreamTokenizer cin=new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
public static PrintWriter cout=new PrintWriter(new OutputStreamWriter(System.out));
static int N=(int)1e5+4,n,i=0;
static int[] x=new int[N];
static double t;
static double[] a=new double[N],b=new double[N];
static double[][] f=new double[N][2];
static double dp(int i,int st)
{
if(f[i][st]!=0) return f[i][st];
f[i][0]=Math.min(dp(i-1,0)+x[i]-x[i-1],dp(i-1,1)+b[i]/1.3);
f[i][1]=Math.min(dp(i-1,0)+(x[i]-x[i-1])+a[i]/0.7,dp(i-1,1)+(b[i]>a[i] ? (b[i]-a[i])/1.3 : (a[i]-b[i])/0.7 ));
return f[i][st];
}
public static void main(String[] args) throws IOException {
n=nextInt();
for(int i=1;i<=n;i++)
{
x[i]=nextInt();
}
for(int i=1;i<=n-1;i++)
{
a[i]=nextDouble();
b[i+1]=nextDouble();
}
f[1][0]=x[1];
f[1][1]=x[1]+a[1]/0.7;
double ans=dp(n,0);
cout.printf("%.2f",ans);
cout.flush();
}
public static int nextInt() throws IOException {
cin.nextToken();
return (int)cin.nval;
}
public static long nextLong() throws IOException {
cin.nextToken();
return (long)cin.nval;
}
public static double nextDouble() throws IOException {
cin.nextToken();
return cin.nval;
}
public static String nextString() throws IOException {
cin.nextToken();
return cin.sval;
}
public static void closeAll()
{
cout.close();
}
}
- 好长时间没做dp,没想到dp,一开始用的大模拟,写了两个小时也没写出来,看wp才知道是dp,这个形式确实是一个很简单的dp
买二赠一70%(贪心,队列)


import java.io.*;
import java.util.*;
public class Main {
public static StreamTokenizer cin=new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
public static PrintWriter cout=new PrintWriter(new OutputStreamWriter(System.out));
static int N=(int)5e5+3,n,ans;
static int[] a=new int[N];
public static void main(String[] args) throws IOException {
n=nextInt();
for(int i=1;i<=n;i++)
{
a[i]=nextInt();
// cout.println(i+" "+a[i]);
}
Arrays.sort(a,1,1+n);
// for(int i=1;i<=n;i++) cout.println(i+" "+a[i]);
Deque<Integer> queue=new ArrayDeque<>();
int cnt=0;
for(int i=n;i>0;i--)
{
// cout.println(i+" "+a[i]);
if(!queue.isEmpty()&&queue.getFirst()>=a[i])
{
queue.removeFirst();
continue;
}
cnt++;ans+=a[i];
if((cnt&1)==0) queue.addLast(a[i]/2);
}
cout.println(ans);
cout.flush();
}
public static int nextInt() throws IOException {
cin.nextToken();
return (int)cin.nval;
}
public static long nextLong() throws IOException {
cin.nextToken();
return (long)cin.nval;
}
public static double nextDouble() throws IOException {
cin.nextToken();
return cin.nval;
}
public static String nextString() throws IOException {
cin.nextToken();
return cin.sval;
}
public static void closeAll()
{
cout.close();
}
}
- 一开始想到贪心没敢用,不知道怎么证明,到最后也没写。
- 以后想到贪心,如果证明不出来也没事,先写了再说,可以看后面的题。
合并石子(区间dp)
最大开支(数学函数,贪心,优先队列)




暴力:过30%
package lqb;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.StreamTokenizer;
public class Main {
// public static StreamTokenizer cin=new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
// public static PrintWriter cout=new PrintWriter(new OutputStreamWriter(System.out));
static StreamTokenizer cin=new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
static PrintWriter cout=new PrintWriter(new OutputStreamWriter(System.out));
static int N=(int)1e5+5,n,m,ans,sum;
static int[] k=new int[N],b=new int[N],x0=new int[N];
static int[][] t=new int[N][2];
static void dfs(int now,int scnt)
{
if(now==m)
{
ans=Math.max(ans,sum);
// for(int i=0;i<m;i++) cout.print(t[i][0]+" ");
// cout.println();
// for(int i=0;i<m;i++) cout.print(t[i][1]+" ");
// cout.println();
// cout.println(ans+" "+sum);
// cout.println("------------------------");
return;
}
for(int i=0;i<=scnt;i++)
{
sum+=i*Math.max(k[now]*i+b[now],0);
t[now][0]=i;t[now][1]=i*Math.max(k[now]*i+b[now],0);
dfs(now+1,scnt-i);
sum-=i*Math.max(k[now]*i+b[now],0);
}
}
public static void main(String[] args) throws IOException {
n=nextInt();
m=nextInt();
for(int i=0;i<m;i++)
{
k[i]=nextInt();
b[i]=nextInt();
}
dfs(0,n);
cout.println(ans);
cout.flush();
}
public static int nextInt() throws IOException {
cin.nextToken();
return (int)cin.nval;
}
public static long nextLong() throws IOException {
cin.nextToken();
return (long)cin.nval;
}
public static double nextDouble() throws IOException {
cin.nextToken();
return cin.nval;
}
public static String nextString() throws IOException {
cin.nextToken();
return cin.sval;
}
public static void closeAll()
{
cout.close();
}
}
正确做法
package lqb;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.StreamTokenizer;
import java.util.ArrayDeque;
import java.util.Comparator;
import java.util.Deque;
import java.util.PriorityQueue;
public class Main {
// public static StreamTokenizer cin=new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
// public static PrintWriter cout=new PrintWriter(new OutputStreamWriter(System.out));
static StreamTokenizer cin=new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
static PrintWriter cout=new PrintWriter(new OutputStreamWriter(System.out));
public static void main(String[] args) throws IOException {
int k,b,n=nextInt(),m=nextInt();
Comparator<Integer> cp=(o1,o2)-> o2-o1;
PriorityQueue<Integer> pq=new PriorityQueue<Integer>(cp);
Deque<Integer> deque=new ArrayDeque<Integer>();
deque.removeFirst()
for(int i=1;i<=m;i++)
{
k=nextInt();b=nextInt();
for(int j=1;j<=n;j++)
{
int cost=2*k*j-k+b;
if(cost>0)
{
pq.add(cost);
}
else
{
break;
}
}
}
long maxCost=0;
int num=Math.min(n,pq.size());
for(int j=0;j<num;j++)
{
maxCost+=pq.poll();
}
cout.print(maxCost);
cout.flush();
}
public static int nextInt() throws IOException {
cin.nextToken();
return (int)cin.nval;
}
public static long nextLong() throws IOException {
cin.nextToken();
return (long)cin.nval;
}
public static double nextDouble() throws IOException {
cin.nextToken();
return cin.nval;
}
public static String nextString() throws IOException {
cin.nextToken();
return cin.sval;
}
public static void closeAll()
{
cout.close();
}
}
- 通过函数关系找到每一个项目增加一个人增加的钱
cost=2*k*j-k+b;,然后枚举每一个项目到第几个人cost为负,就退出。把每一个cost为正的放入优先队列,由二次函数的性质可以知道,cost最大的一定是人最少的。所以可以放心的取优先队列的第一个数,人数一定是递增的
14届Python B
2023

package lqb;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.StreamTokenizer;
public class Main {
// public static StreamTokenizer cin=new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
// public static PrintWriter cout=new PrintWriter(new OutputStreamWriter(System.out));
static StreamTokenizer cin=new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
static PrintWriter cout=new PrintWriter(new OutputStreamWriter(System.out));
static boolean check(int x) //有2023返回true
{
char[] t=Integer.toString(x).toCharArray();
boolean flag;
int[] num= {2,0,2,3,0};
int j=0;
for(char c:t)
{
if(j==4) break;
if(c==num[j]+'0') j++;
}
if(j==4) return true;
return false;
}
public static void main(String[] args) throws IOException
{
int cnt=0;
// cout.println(check(20322175));
// cout.println(check(33220022));
// cout.println(check(20230415));
// cout.println(check(20193213));
// cout.println(check(20020023));
for(int i=12345678;i<=98765432;i++)
{
if(!check(i)) cnt++;
}
cout.print(cnt);
cout.flush();
System.out.println();
}
public static int nextInt() throws IOException {
cin.nextToken();
return (int)cin.nval;
}
public static long nextLong() throws IOException {
cin.nextToken();
return (long)cin.nval;
}
public static double nextDouble() throws IOException {
cin.nextToken();
return cin.nval;
}
public static String nextString() throws IOException {
cin.nextToken();
return cin.sval;
}
public static void closeAll()
{
cout.close();
}
}
- 写这种大数字的时候要注意。我写循环的时候写成了1234567不是12345678,难绷。
硬币兑换
package lqb;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.StreamTokenizer;
public class Main {
// public static StreamTokenizer cin=new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
// public static PrintWriter cout=new PrintWriter(new OutputStreamWriter(System.out));
static StreamTokenizer cin=new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
static PrintWriter cout=new PrintWriter(new OutputStreamWriter(System.out));
public static void main(String[] args) throws IOException
{
int[] arr=new int[10000];
for(int i=1;i<=2023;i++) arr[i]=i;
int res=0;
int ans=Integer.MIN_VALUE;
for(int i=1;i<=4046;i++)
{
res=0;
for(int j=1;j<=i/2;j++)
{
int k=i-j;
if(k!=j) {
res+=Math.min(arr[k],arr[j]);
}else {
res+=arr[k]/2;
}
}
res+=arr[i];
ans=Math.max(ans,res);
}
cout.print(ans);
cout.flush();
}
public static int nextInt() throws IOException {
cin.nextToken();
return (int)cin.nval;
}
public static long nextLong() throws IOException {
cin.nextToken();
return (long)cin.nval;
}
public static double nextDouble() throws IOException {
cin.nextToken();
return cin.nval;
}
public static String nextString() throws IOException {
cin.nextToken();
return cin.sval;
}
public static void closeAll()
{
cout.close();
}
}

浙公网安备 33010602011771号