1、數字操作
答案:996
算法分析
直接模擬
Java 代碼
public class Main {
public static void main(String[] args) {
int n = 998244353;
int k = 29;
while(k -- > 0)
{
if(n % 10 == 0) n /= 10;
else n -= 1;
}
System.out.println(n);
}
}
2、字符串操作
算法分析
說白了就是貪心的思想,盡可能的往大的字母靠,計算出每個字母有多少個,若當前字母有超過兩個
Java 代碼
public class Main {
static int N = 27;
static int[] cnt = new int[N];
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
char[] g = scan.next().toCharArray();
for(int i = 0;i < g.length;i ++)
{
cnt[g[i] - 'a'] ++;
}
for(int i = 0;i < 25;i ++)
{
if(cnt[i] >= 2)
{
cnt[i + 1] += cnt[i] / 2;
cnt[i] %= 2;
}
}
for(int i = 25;i >= 0;i --)
{
for(int j = cnt[i];j > 0;j --)
System.out.print((char)(i + 'a'));
}
}
}
3、煎牛扒
答案:499122180
算法分析
等價于一次能煎20個,一次需要10分鐘
Java 代碼
public static void main(String[] args){
long n = 998244353;
long cnt = 0;
if(n % 20 == 0) cnt = n / 20;
else cnt = n / 20 + 1;
System.out.println(cnt * 10);
}
4、數列求值
答案:959741112
算法分析
模擬,注意需要開longlong
Java代碼
static int N = 20200202;
static long[] a = new long[N + 10];
static int mod = 998244353;
public static void main(String[] args){
a[1] = 1;
a[2] = 1;
a[3] = 1;
for(int i = 4;i <= N;i ++)
{
a[i] = (7 * a[i - 1] + 10 * a[i - 2] + 6 * a[i - 3]) % mod;
}
System.out.println(a[N]);
}
5、卡片游戲
答案
算法分析
爆搜所有的情況,當君選了左邊或者右邊時,妹都能通過貪心的算法固定選一個,在給定的區間中,dfs(start,end,v)
表示搜索到當前區間[start,end]
,君比妹多v
的價值
- 當君選了
a[start]
若a[start + 1] >= a[end]
,則妹就會選a[start + 1]
,區間縮到[start + 2,end]
,否則選擇a[end]
,區間縮到[start + 1,end - 1]
- 當君選了
a[end]
若a[start] >= a[end - 1]
,則妹就會選a[start]
,區間縮到[start + 1,end - 1]
,否則選擇a[end - 1]
,區間縮到[start,end - 2]
這樣子做的跑的次數是2^50
,大概是10^15
次,1秒跑10^8
次左右,基本要跑幾個小時的,因此需要進行優化,由上面的遞歸過程可以發現,當區間固定時,該區間得到的差值一定是固定的,因此可以用記憶化搜索把當前區間的答案存儲下來
Java 代碼(爆搜版)
import java.util.Scanner;
public class Main {
static int N = 110;
static int[] a = new int[N];
static int ans = Integer.MIN_VALUE;
static void dfs(int start,int end,int v)
{
if(start > end)
{
ans = Math.max(ans, v);
return;
}
//拿start
if(a[start + 1] >= a[end]) dfs(start + 2,end,v + a[start] - a[start + 1]);
else dfs(start + 1,end - 1,v + a[start] - a[end]);
//拿end
if(a[start] >= a[end - 1]) dfs(start + 1,end - 1,v + a[end] - a[start]);
else dfs(start,end - 2,v + a[end] - a[end - 1]);
}
public static void main(String[] args){
Scanner scan = new Scanner(System.in);
int n = scan.nextInt();
for(int i = 1;i <= n;i ++) a[i] = scan.nextInt();
dfs(1,n,0);
System.out.println(ans);
}
}
Java 代碼(記憶化搜索版)
import java.util.Arrays;
import java.util.Scanner;
public class Main {
static int N = 110;
static int[] a = new int[N];
static int[][] f = new int[N][N];
static int dfs(int start,int end)
{
if(start > end) return 0;
if(f[start][end] != -1) return f[start][end];
//拿start
f[start][end] = -0x3f3f3f3f;
if(a[start + 1] >= a[end])
f[start][end] = Math.max(f[start][end],dfs(start + 2,end) + a[start] - a[start + 1]);
else
f[start][end] = Math.max(f[start][end],dfs(start + 1,end - 1) + a[start] - a[end]);
//拿end
if(a[start] >= a[end - 1])
f[start][end] = Math.max(f[start][end], dfs(start + 1,end - 1) + a[end] - a[start]);
else
f[start][end] = Math.max(f[start][end], dfs(start,end - 2) + a[end] - a[end - 1]);
return f[start][end];
}
public static void main(String[] args){
Scanner scan = new Scanner(System.in);
int n = scan.nextInt();
for(int i = 1;i <= n;i ++) a[i] = scan.nextInt();
for(int i = 0;i <= n;i ++) Arrays.fill(f[i], -1);
System.out.println(dfs(1,n));
}
}
6、打字
算法分析
用數組模擬?;蛘邨DM操作
Space
:加一個'#'
代表空格,最后輸出的時候判斷即可
CapsLock
:切換大小寫,state
為 false
表示小寫,true
表示大寫
Backspace
:刪除元素
字母
:需要判斷state
是表示小寫還是大寫,再添加到數組中
時間復雜度
Java 代碼
import java.util.Scanner;
public class Main {
static int N = 100010;
static char[] ans = new char[N];
static int k = 0;
static boolean state = false;//一開始是小寫
public static void main(String[] args){
Scanner scan = new Scanner(System.in);
int n = scan.nextInt();
while(n -- > 0)
{
String op = scan.next();
if(op.equals("Space"))
{
ans[++ k] = '#';
}
else if(op.equals("CapsLock"))
{
state = state ? false : true;
}
else if(op.equals("Backspace"))
{
if(k >= 1) k --;
}
else
{
char t = op.toCharArray()[0];
if(state)
{
ans[++ k] = (char)(t - ('a' - 'A'));
}
else ans[++ k] = t;
}
}
for(int i = 1;i <= k;i ++)
{
if(ans[i] == '#') System.out.print(" ");
else System.out.print(ans[i]);
}
}
}
7、刪除字符
算法分析
記錄所有字母在某些位置出現過用鏈表記錄,比如a
字符在2
,3
,5
位置出現過,則用鏈表存儲2
,3
,5
,從a
到z
枚舉每個鏈表,標記需要刪除的字符,最后枚舉所有的元素,若該元素沒有刪除過則輸出
時間復雜度
Java 代碼
import java.util.ArrayList;
import java.util.Scanner;
public class Main {
static int N = 100010;
static char[] g;
static ArrayList[] list = new ArrayList[26];
static boolean[] bool = new boolean[N];
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
int n = scan.nextInt();
int k = scan.nextInt();
g = scan.next().toCharArray();
for(int i = 0;i < 26;i ++) list[i] = new ArrayList<Integer>();
for(int i = 0;i < n;i ++)
{
int idx = g[i] - 'a';
list[idx].add(i);
}
for(int i = 0;i < 26;i ++)
{
for(Object item : list[i])
{
int x = (int) item;
bool[x] = true;
k --;
if(k == 0) break;
}
if(k == 0) break;
}
String ans = "";
for(int i = 0;i < n;i ++)
{
if(!bool[i]) ans += g[i];
}
System.out.println(ans);
}
}
8、兩個數組
算法分析
在a[]
數組中,將x
轉化為x + y
,和x - y
,能否把a[]
全部元素變成一致,
- 1、先求出一步的最少距離是多少,即求出
b[]
數組所有元素的最大公約數c
- 2、判斷
a[]
數組任意的兩個元素能否通過走最少距離的走在一起,即判斷任意的a[i]
,和a[j]
的距離t = a[i] - a[j]
,能否全能整除c
,若能返回Yes
,否則返回false
時間復雜度
Java 代碼
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
public class Main {
static int N = 100010;
static int n, m;
static int[] a = new int[N];
static int[] b = new int[N];
static int gcd(int a, int b) {
return b == 0 ? a : gcd(b, a % b);
}
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int T = Integer.parseInt(br.readLine());
while (T-- > 0) {
String[] s1 = br.readLine().split(" ");
n = Integer.parseInt(s1[0]);
m = Integer.parseInt(s1[1]);
String[] s2 = br.readLine().split(" ");
for (int i = 0; i < n; i++)
a[i] = Integer.parseInt(s2[i]);
Arrays.sort(a, 0, n);
String[] s3 = br.readLine().split(" ");
for (int i = 0; i < m; i++)
b[i] = Integer.parseInt(s3[i]);
// 求b數組的最大公約數
int c = b[0];
for (int i = 1; i < m; i++) {
c = gcd(c, b[i]);
}
if (c == 1)
System.out.println("Yes");
else {
boolean flag = true;
// 求a數組的每兩個數的間隔是否都是b數組最大公約數的倍數
for (int i = 1; i < n; i++) {
int t = a[i] - a[i - 1];
if (t % c != 0) {
flag = false;
break;
}
}
if (flag)
System.out.println("Yes");
else
System.out.println("No");
}
}
}
}
9、數組求和
算法分析
假設當前a[]
數組已固定,b[]
數組已經進行了重排列,即f[i,i] = a[i] * b[i]
已固定,求圖中所有區間的總和
image.png
即
...
...
又由于a[i]
是固定的,因此a[i]
需要和 (n - i + 1) * i
進行連體搭配,即一定是固定的,相當于轉換成給定數組A[]
,重排列B[]
,求所有A[i] + B[i]
總和的最小值,讓A[]
的第一大與B[]
最小搭配,讓A[]
的第二大合B[]
第二小搭配...,即對A[]
和B[]
進行排序,然后進行搭配
時間復雜度
Java 代碼
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
public class Main {
static int N = 100010;
static int mod = 998244353;
static int n,m;
static Long[] a = new Long[N];
static Long[] b = new Long[N];
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int n = Integer.parseInt(br.readLine());
String[] s1 = br.readLine().split(" ");
for(int i = 1;i <= n;i ++) a[i] = Long.parseLong(s1[i - 1]);
String[] s2 = br.readLine().split(" ");
for(int i = 1;i <= n;i ++) b[i] = Long.parseLong(s2[i - 1]);
for(int i = 1;i <= n;i ++)
{
a[i] = a[i] * (n - i + 1) * i;
}
Arrays.sort(a,1,n + 1);
Arrays.sort(b,1,n + 1);
long S = 0;
for(int i = 1;i <= n;i ++)
{
S = (S + (a[i] % mod) * b[n - i + 1]) % mod;
}
System.out.println(S);
}
}