Logo lxn 的博客

博客

标签
暂无

20240221寒假单元测验题解

本文章由 WyOJ Shojo 从洛谷专栏拉取,原发布时间为 2024-01-29 21:14:45

T316849 人数

考察最值、排序等。可以用最值,也可以用sort、桶排序等。

T311007 优秀的码字

本题考察枚举及其优化。

枚举:枚举第$i,j$个字符串$(i<j)$再判断其不同子串的个数。时间复杂度$O(n^2m)$

如何优化?

  1. 当出现小于$k$的距离,立即退出。

  2. 数学优化。在 $60%$数据基础上另有 $40%$ 的数据 $N>2^m $ 根据鸽笼原理,那么必然有两个相同的字符。一定不符合要求。

参考代码:

#include <bits\/stdc++.h>
using namespace std;
typedef long long LL;

const int maxn=222;
string ss[maxn];

int main()
{
	int N,M,K;scanf("%d%d%d",&N,&M,&K);
	if(N>(1LL<<M))return puts("No"),0;
	for(int i=1;i<=N;++i) cin>>ss[i];
	sort(ss+1,ss+1+N);\/\/排序可以找出更近的符号。
	for(int i=1;i<=N;++i)
	{
		int dis=0,j=i+1;
		for(int k=0;k<M;++k)if(ss[i][k]!=ss[j][k]) ++dis;
		if(dis<K) return puts("No"),0;
	}
	
	for(int i=1;i<=N;++i)
  		for(int j=i+2;j<=N;++j)
	{
		int dis=0;
		for(int k=0;k<M;++k)if(ss[i][k]!=ss[j][k]) ++dis;
		if(dis<K) return puts("No"),0;
	}
	return puts("Yes"),0;
}

T3 挑战赛

考察内容:排序+贪心。 什么情况下一个人能拍到榜首呢?

自己先拿到最高分,让后其余的选手得分尽量低。

其他选手怎样得分尽量低呢?

$a_i$低的人本轮得到高分,高的人得到低分,那么有更多的人可以排名更高。

因为题目中讨论的是机会,可以从最有力一个选手的角度出发安排战局。

参考代码:

#include<bits\/stdc++.h> 
using namespace std;
const int N=3e5+114; 
int a[N];
bool cmp(int x,int y){
    return x>y;
}
int main(){
	int n,maxx=0,sum=0;
    cin>>n;
    for(int i=1;i<=n;i++){
    	cin>>a[i];
	} 
    sort(a+1,a+1+n,cmp);
    for(int i=1;i<=n;i++){\/\/高分的人本次得到小分。
        maxx=max(maxx,a[i]+i);
    }
    for(int i=1;i<=n;i++){
    	if(a[i]+n>=maxx) sum++;
	}
    cout<<sum;
    return 0;
}

方法二 zrul 二分如果一个排名x能拿第一,排名比x高的一定能na第一

#include<bits\/stdc++.h>
#define int long long
#define inl inline
#define reg register
#define N 300005
#define INF 2147483647
using namespace std;
int n,a[N],b[N];
inl int read(){
   reg int f=1,x=0;
   reg char ch=getchar();
   while(ch<'0'||ch>'9'){
       if(ch=='-') f=-1;
       ch=getchar();
   }
   while(ch>='0'&&ch<='9'){
       x=(x<<1)+(x<<3)+(ch^48);
       ch=getchar();
   }
   return f*x;
}
inl void write(int x){
   if(x<0) x=-x;
   if(x>=10) write(x\/10);
   putchar(x%10^48);
}
bool check(int x){
	int tot=n-1;
	for(int i=1;i<=n;i++,tot--)
		if(b[i]!=a[x]&&(b[i]+tot>a[x]+n||b[i]+tot==a[x]+n&&i<x)) return false;
	return true;
}
int lower(){
	int l=1,r=n,mid=0,ans=0;
	while(l<=r){
		mid=l+r>>1;
		if(check(mid)){
			ans=mid;
			l=mid+1;
		}else r=mid-1;
	}
	return ans;
}
signed main(){
   n=read();
   for(int i=1;i<=n;++i) a[i]=read();
   memcpy(b,a,sizeof(a));
   sort(a+1,a+n+1,greater<int>());
   sort(b+1,b+n+1);
  	write(lower());
   return 0;
}

T316918 爬楼梯

本题考察了递推和高精度加法。

设$f[i]$为达到第$i$层楼梯的方案数。 则$f[i]=f[i-1]+f[i-2]+f[i-3],i>3$

初始条件为$f[1]=1,f[2]=2,f[3]=4$,数据范围较大,需要用高精度加法。

参考代码:

#include<iostream>
#include<cstdio>
using namespace std;
int n,f[5010][5010],len;
void add(int k) { \/\/高精加法
	for(int i=1; i<=len; i++)\/\/两数相加
		f[k][i]=f[k-1][i]+f[k-2][i]+f[k-3][i];
	for(int i=1; i<=len; i++) { \/\/进位
		f[k][i+1]+=f[k][i]\/10;
		f[k][i]%=10;
	}
	if(f[k][len+1]>0)len++;
}
int main() {

	cin>>n;
	len=1;
	f[1][1]=1;\/\/预处理
	f[2][1]=2;\/\/预处理
	f[3][1]=4;
	for(int i=4; i<=n; i++)\/\/开始计算
		add(i);
	
	for(int j=len; j>=1; j--)\/\/输出
		cout<<f[n][j];
	cout<<endl;
	return 0;
}

T316902 分糖果

本题的要求最大值最小,二分答案的标志性名次。那么分析本题具有单调性吗?

根据题意,小朋友们得到的糖果数越平均越好。蛀牙值越大,每个小朋友分的糖果数越多,分的份数就越少。否则越多。

我们二分蛀牙值,如果分完后糖果有剩余,就还要增大;如果不够分的,就要缩小。

参考代码:

#include <iostream>  
using namespace std;
long long n,m,l=1,r,ans;
long long a[300010];
bool check(long long x){ \/\/x 是当前的蛀牙值
	long long sum=0;
	for(int i=1;i<=m;i++) sum+=(a[i]+x-1)\/x;
	return sum<=n;
} 
int main(){
	cin>>n>>m;
	for(int i=1;i<=m;i++){cin>>a[i];r+=a[i];} \/\/mid 的极限是总共的球数 
	while(l<r){	\/\/二分模板 
		long long mid=(l+r)\/2+1;
		if(check(mid)){r=mid-1;ans=mid;}
		else l=mid;
	}
	cout<<ans;
	return 0; 
}

T310718 花园

本题考察了结构体和集合的容斥。

要处理重合的部分 矩形的交集

我们给定了矩形的对角线的两个端点,但没有说明大小,要统一为左上角和右下角,然后,找到交集部分。

如何找到交集部分?共有四个横坐标,四个纵坐标,找到中间的两个。

参考代码:

#include <iostream>
#include <iomanip>
#include<stdio.h> 
using namespace std;
typedef long long ll;
struct node{\/\/左上角 和右下角 
	ll xa,ya,xb,yb;
}jx1,jx2,jx3;
int n;

node le_ri(){
	node t;
	cin>>t.xa>>t.ya>>t.xb>>t.yb;
	if(t.xa>t.xb)swap(t.xa,t.xb);
	if(t.ya>t.yb)swap(t.ya,t.yb);
	return t;
}
ll s(node t){
	return (t.xb-t.xa)*(t.yb-t.ya);
}
int main()
{
    
	cin>>n;
    jx1=le_ri();
    if(n==1){
    	cout<<s(jx1)<<endl;
    	return 0;
	}
	jx2=le_ri();
	if(jx1.xa>=jx2.xb||jx1.xb<=jx2.xa||jx1.ya>=jx2.yb||jx1.yb<=jx2.ya) {\/\/2在1的左侧,右侧,下侧,上侧 
		cout<<s(jx1)+s(jx2)<<endl;
		return 0;
	}
	\/\/相交的情况
	 jx3.xa=max(jx1.xa,jx2.xa);
	 jx3.xb=min(jx1.xb,jx2.xb);
	 jx3.ya=max(jx1.ya,jx2.ya);
	 jx3.yb=min(jx1.yb,jx2.yb);
	 cout<<s(jx1)+s(jx2)-s(jx3)<<endl;
       
}

ABC246

本文章由 WyOJ Shojo 从洛谷专栏拉取,原发布时间为 2024-02-27 13:57:34

[ABC246C] Coupon

题面翻译

商店里有 $N$ 件商品,第 $i$ 件物品价格 $A_i$ 元。

有 $K$ 张优惠券,一个优惠券可以用于一个物品上,同一个物品可以使用若干张优惠券(可能不使用优惠券)。

一张优惠券可以降低价格 $X$ 元,在 $a$ 元的物品上使用 $k$ 张优惠券后的价格降低为 $\max{a - kX, 0 }$ 元。

请求出买下所有物品的最少价格。

题目描述

输入格式

入力は以下の形式で標準入力から与えられる。

$ N $ $ K $

$ X $ $ A_1 $ $ A_2 $ $ \ldots $ $ A_N $

输出格式

答えを出力せよ。

样例 #1

样例输入 #1

5 4 7
8 3 10 5 13

样例输出 #1

12

样例 #2

样例输入 #2

5 100 7
8 3 10 5 13

样例输出 #2

0

样例 #3

样例输入 #3

20 815 60
2066 3193 2325 4030 3725 1669 1969 763 1653 159 5311 5341 4671 2374 4513 285 810 742 2981 202

样例输出 #3

112

提示

制約

  • $ 1\ \leq\ N\ \leq\ 2\ \times\ 10^5 $
  • $ 1\ \leq\ K,\ X\ \leq\ 10^9 $
  • $ 1\ \leq\ A_i\ \leq\ 10^9 $
  • 入力はすべて整数

Sample Explanation 1

$ 1 $ 番目の商品に対してクーポン $ 1 $ 枚、$ 3 $ 番目の商品に対してクーポン $ 1 $ 枚、$ 5 $ 番目の商品に対してクーポン $ 2 $ 枚を使用すると、 - $ 1 $ 番目の商品を $ \max\lbrace\ A_1-X,\ 0\ \rbrace\ =\ 1 $ 円で買うことができ、 - $ 2 $ 番目の商品を $ \max\lbrace\ A_2,\ 0\ \rbrace\ =\ 3 $ 円で買うことができ、 - $ 3 $ 番目の商品を $ \max\lbrace\ A_3-X,\ 0\ \rbrace\ =\ 3 $ 円で買うことができ、 - $ 4 $ 番目の商品を $ \max\lbrace\ A_4,\ 0\ \rbrace\ =\ 5 $ 円で買うことができ、 - $ 5 $ 番目の商品を $ \max\lbrace\ A_5-2X,\ 0\ \rbrace\ =\ 0 $ 円で買うことができます。 よって、すべての商品を $ 1\ +\ 3\ +\ 3\ +\ 5\ +\ 0\ =\ 12 $ 円で買うことができ、これが最小です。

[ABC246D] 2-variable Function

题面翻译

给定整数 $N$,请你找到最小的整数 $X$,满足:

  • $X \ge N$
  • 存在一对非负整数 $(a, b)$,使得 $X = a^3 + a^2b + ab^2 + b^3$。

题目描述

输入格式

入力は以下の形式で標準入力から与えられる。

$ N $

输出格式

答えを整数として出力せよ。

样例 #1

样例输入 #1

9

样例输出 #1

15

样例 #2

样例输入 #2

0

样例输出 #2

0

样例 #3

样例输入 #3

999999999989449206

样例输出 #3

1000000000000000000

提示

制約

  • $ N $ は整数
  • $ 0\ \le\ N\ \le\ 10^{18} $

Sample Explanation 1

$ 9\ \le\ X\ \le\ 14 $ であるようなどの整数 $ X $ についても、問題文中の条件を満たすような $ (a,b) $ は存在しません。 $ X=15 $ は $ (a,b)=(2,1) $ とすると問題文中の条件を満たします。

Sample Explanation 2

$ N $ 自身が条件を満たすこともあります。

Sample Explanation 3

入出力が $ 32 $bit 整数型に収まらない場合があります。

[ABC263E] Sugoroku 3

题面翻译

题目描述

一共有 $N$ 个格子编号 $1$ 到 $N$。有一个人站在 $1$ 号格子。

对于 $\forall i \in [1,N-1]$ 号格子有一个 $A_i + 1$ 面的骰子,写有 $0$ 到 $A_i$ 这些数。如果 ta 掷到了 $k$,他将往前走 $k$ 格,走到 $i+k$ 号方格。

求走到 $N$ 号方格的期望次数。对 $998244353$ 取模。

输入格式

第一行一个正整数 $N$,第二行 $N-1$ 个正整数表示 $A_i$。

输出格式

如果期望次数为 $\frac{P}{Q}$,输入最小非负整数 $R$ 使得 $R\times Q \equiv P\pmod {998244353}$。

数据范围

$2\leq N\leq 2\times 10^5$

$\forall i \in [1,N-1],1\leq A_i\leq N-i$

题目描述

输入格式

入力は以下の形式で標準入力から与えられる。

$ N $ $ A_1 $ $ A_2 $ $ \dots $ $ A_{N-1} $

输出格式

答えを出力せよ。

样例 #1

样例输入 #1

3
1 1

样例输出 #1

4

样例 #2

样例输入 #2

5
3 1 2 1

样例输出 #2

332748122

提示

注記

求める期待値は必ず有理数となることが証明できます。またこの問題の制約下では、その値を互いに素な $ 2 $ つの整数 $ P $, $ Q $ を用いて $ \frac{P}{Q} $ と表したとき、$ R\ \times\ Q\ \equiv\ P\pmod{998244353} $ かつ $ 0\ \leq\ R\ \lt\ 998244353 $ を満たす整数 $ R $ がただ一つ存在することが証明できます。この $ R $ を求めてください。

制約

  • $ 2\ \le\ N\ \le\ 2\ \times\ 10^5 $
  • $ 1\ \le\ A_i\ \le\ N-i(1\ \le\ i\ \le\ N-1) $
  • 入力は全て整数。

Sample Explanation 1

求める期待値は $ 4 $ であるため、$ 4 $ を出力します。 マス $ N $ に到達するまでの流れとしては、以下のようなものが考えられます。 - マス $ 1 $ で $ 1 $ を出し、マス $ 2 $ に移動する。 - マス $ 2 $ で $ 0 $ を出し、移動しない。 - マス $ 2 $ で $ 1 $ を出し、マス $ 3 $ に移動する。 このようになる確率は $ \frac{1}{8} $ です。

[ABC246F] typewriter

题面翻译

给定 $ n $ 个字符串,字符集为小写字母,可以任意选择一个字符串,作为字符库,然后(可多次选择同一字符)任意组成长度为 $ l $ 的字符串,求一共能形成多少种长度为 $ l $ 的字符串。

请输出方案数模 $998244353$。

题目描述

$ N $ 段からなるタイプライターがあります。このうち、上から $ i $ 段目のキーでは文字列 $ S_i $ に含まれる文字が打てます。

このキーボードを使って、以下のルールで文字列をひとつ入力することを考えます。

  • まず、整数 $ 1\ \le\ k\ \le\ N $ を選択する。
  • その後、空文字列から始めて、上から $ k $ 段目にあるキーだけを使ってちょうど $ L $ 文字の文字列を入力する。

このルールに従って入力可能な $ L $ 文字の文字列は何通りありますか? 答えは非常に大きくなる場合があるので $ 998244353 $ で割った余りを出力してください。

输入格式

入力は以下の形式で標準入力から与えられる。

$ N $ $ L $ $ S_1 $ $ S_2 $ $ \dots $ $ S_N $

输出格式

答えを出力せよ。

样例 #1

样例输入 #1

2 2
ab
ac

样例输出 #1

7

样例 #2

样例输入 #2

4 3
abcdefg
hijklmnop
qrstuv
wxyz

样例输出 #2

1352

样例 #3

样例输入 #3

5 1000000000
abc
acde
cefg
abcfh
dghi

样例输出 #3

346462871

提示

制約

  • $ N,L $ は整数
  • $ 1\ \le\ N\ \le\ 18 $
  • $ 1\ \le\ L\ \le\ 10^9 $
  • $ S_i $ は abcdefghijklmnopqrstuvwxyz の(連続とは限らない)空でない部分列

Sample Explanation 1

入力可能な文字列は aa, ab, ac, ba, bb, ca, cc の $ 7 $ つです。

Sample Explanation 3

答えを $ 998244353 $ で割った余りを出力してください。

[ABC246G] Game on Tree 3

题面翻译

给定一棵树,有点权,B 初始在 $ 1 $,每轮 A 选择一个点将权值变为 $ 0 $,然后 B 移动一次,B 可在任意时刻停止游戏然后获得所在点上的权值的得分,两人均采取最优策略那么最终 B 最少会拿到多少的得分。

题目描述

$ N $ 個の頂点を持ち、頂点 $ 1 $ を根とする根付き木があります。 $ i\ =\ 1,\ 2,\ \ldots,\ N-1 $ について、$ i $ 本目の辺は頂点 $ u_i $ と頂点 $ v_i $ を結びます。 また、根以外の頂点には正の整数が書かれており、具体的には、$ i\ =\ 2,\ 3,\ \ldots,\ N $ について、頂点 $ i $ に正の整数 $ A_i $ が書かれています。 高橋君と青木君はこの根付き木と $ 1 $ 個のコマを使って次の対戦ゲームをします。

はじめ、頂点 $ 1 $ にコマが置かれています。その後、ゲームが終了するまで下記の手順を繰り返します。

  1. まず、青木君が根以外の頂点を任意に $ 1 $ 個選び、その頂点に書かれた整数を $ 0 $ に書き換える。
  2. 次に、高橋君がコマを、いまコマがある頂点の(直接の)子のいずれかに移動する。
  3. その後、コマが葉にある場合はゲームが終了する。そうでない場合であっても、高橋君は望むならゲームを直ちに終了させることができる。

ゲーム終了時点でコマがある頂点に、ゲーム終了時点で書かれている整数が、高橋君の得点となります。 高橋君は自身の得点を出来るだけ大きく、青木君は高橋君の得点を出来るだけ小さくしたいです。 両者がそのために最適な行動を取るときの高橋君の得点を出力してください。

输入格式

入力は以下の形式で標準入力から与えられる。

$ N $ $ A_2 $ $ \ldots $ $ A_N $ $ u_1 $ $ v_1 $ $ u_2 $ $ v_2 $ $ \ dots $ $ u_{N-1} $ $ v_{N-1} $

输出格式

答えを出力せよ。

样例 #1

样例输入 #1

7
2 4 6 5 6 10
1 2
1 3
2 4
2 5
5 6
5 7

样例输出 #1

5

样例 #2

样例输入 #2

30
29 27 79 27 30 4 93 89 44 88 70 75 96 3 78 39 97 12 53 62 32 38 84 49 93 53 26 13 25
13 15
14 22
17 24
12 3
4 3
5 8
26 15
3 2
2 9
4 25
4 13
2 10
28 15
6 4
2 5
19 9
2 7
2 14
23 30
17 2
7 16
21 13
13 23
13 20
1 2
6 18
27 6
21 29
11 8

样例输出 #2

70

提示

制約

  • $ 2\ \leq\ N\ \leq\ 2\ \times\ 10^5 $
  • $ 1\ \leq\ A_i\ \leq\ 10^9 $
  • $ 1\ \leq\ u_i,\ v_i\ \leq\ N $
  • 与えられるグラフは木である。
  • 入力はすべて整数

Sample Explanation 1

両者が最適な行動をとる場合のゲームの進行の一例として次のものがあります。 1. はじめ、コマは頂点 $ 1 $ に置かれています。 2. 青木君が頂点 $ 7 $ に書かれた整数を $ 10 $ から $ 0 $ に書き換えます。 3. 高橋君がコマを頂点 $ 1 $ から頂点 $ 2 $ に動かします。 4. 青木君が頂点 $ 4 $ に書かれた整数を $ 6 $ から $ 0 $ に書き換えます。 5. 高橋君がコマを頂点 $ 2 $ から頂点 $ 5 $ に動かします。 6. 高橋君がゲームを終了します。 ゲーム終了時点でコマは頂点 $ 5 $ にあり、頂点 $ 5 $ にはゲーム終了時点で整数 $ 5 $ が書かれているので、高橋君の得点は $ 5 $ です。

C题大赛-A-E

本文章由 WyOJ Shojo 从洛谷专栏拉取,原发布时间为 2024-02-27 19:31:47

A:

Doremy's Perfect Math Class

题面翻译

给定一个正整数集合 $S$。对于 $S$,你可以执行以下操作若干次:

  • 从集合中选两个数 $x$ 和 $y$,使得 $x$ 和 $y$ 满足 $x>y$ 并且 $x-y$ 不在集合 $S$ 中。
  • 将 $x-y$ 作为一个新元素加入到集合中。

假设操作方式是最优的,输出到无法操作时集合 $S$ 的最大长度。题目保证结果有限。

题目描述

"Everybody! Doremy's Perfect Math Class is about to start! Come and do your best if you want to have as much IQ as me!" In today's math class, Doremy is teaching everyone subtraction. Now she gives you a quiz to prove that you are paying attention in class.

You are given a set $ S $ containing positive integers. You may perform the following operation some (possibly zero) number of times:

  • choose two integers $ x $ and $ y $ from the set $ S $ such that $ x > y $ and $ x - y $ is not in the set $ S $ .
  • add $ x-y $ into the set $ S $ .

You need to tell Doremy the maximum possible number of integers in $ S $ if the operations are performed optimally. It can be proven that this number is finite.

输入格式

The input consists of multiple test cases. The first line contains a single integer $ t $ ( $ 1\le t\le 10^4 $ ) — the number of test cases. The description of the test cases follows.

The first line contains an integer $ n $ ( $ 2 \le n\le 10^5 $ ) — the size of the set $ S $ .

The second line contains $ n $ integers $ a_1,a_2,\dots,a_n $ ( $ 1\le a_1 < a_2 < \cdots < a_n \le 10^9 $ ) — the positive integers in $ S $ .

It is guaranteed that the sum of $ n $ over all test cases does not exceed $ 2\cdot 10^5 $ .

输出格式

For each test case, you need to output the maximum possible number of integers in $ S $ . It can be proven that this value is finite.

样例 #1

样例输入 #1

2
2
1 2
3
5 10 25

样例输出 #1

2
5

提示

In the first test case, no such $ x $ and $ y $ exist. The maximum possible number of integers in $ S $ is $ 2 $ .

In the second test case,

  • $ S=\{5,10,25\} $ at first. You can choose $ x=25 $ , $ y=10 $ , then add $ x-y=15 $ to the set.
  • $ S=\{5,10,15,25\} $ now. You can choose $ x=25 $ , $ y=5 $ , then add $ x-y=20 $ to the set.
  • $ S=\{5,10,15,20,25\} $ now. You can not perform any operation now.

After performing all operations, the number of integers in $ S $ is $ 5 $ . It can be proven that no other sequence of operations allows $ S $ to contain more than $ 5 $ integers.

B:

Prime Square

题面翻译

定义一个$n\times n$素数正方形为:

  • 所有的数不大于$10^5$
  • 所有的数不是质数
  • 每行、每列的和都是质数

输入$n$,输出大小为$n$的素数正方形

翻译 by jun头吉吉

题目描述

Sasha likes investigating different math objects, for example, magic squares. But Sasha understands that magic squares have already been studied by hundreds of people, so he sees no sense of studying them further. Instead, he invented his own type of square — a prime square.

A square of size $ n \times n $ is called prime if the following three conditions are held simultaneously:

  • all numbers on the square are non-negative integers not exceeding $ 10^5 $ ;
  • there are no prime numbers in the square;
  • sums of integers in each row and each column are prime numbers.

Sasha has an integer $ n $ . He asks you to find any prime square of size $ n \times n $ . Sasha is absolutely sure such squares exist, so just help him!

输入格式

The first line contains a single integer $ t $ ( $ 1 \le t \le 10 $ ) — the number of test cases.

Each of the next $ t $ lines contains a single integer $ n $ ( $ 2 \le n \le 100 $ ) — the required size of a square.

输出格式

For each test case print $ n $ lines, each containing $ n $ integers — the prime square you built. If there are multiple answers, print any.

样例 #1

样例输入 #1

2
4
2

样例输出 #1

4 6 8 1
4 9 9 9
4 10 10 65
1 4 4 4
1 1
1 1

C:

Numbers on Whiteboard

题面翻译

$T$ 次询问,对于每一次询问:

给定 $n$ 个数,为 $1,2,3,...,n$,每次可以选择两个数 $a,b$ 并删除,然后把 $\left\lceil\frac{a+b}{2}\right\rceil$ 加入到这些数中。最小化最后剩下的一个数,输出这个数并且输出构造方案。

$2\leq n\leq 2\cdot10^5,\sum n \leq 2\cdot10^5$

题目描述

Numbers $ 1, 2, 3, \dots n $ (each integer from $ 1 $ to $ n $ once) are written on a board. In one operation you can erase any two numbers $ a $ and $ b $ from the board and write one integer $ \frac{a + b}{2} $ rounded up instead.

You should perform the given operation $ n - 1 $ times and make the resulting number that will be left on the board as small as possible.

For example, if $ n = 4 $ , the following course of action is optimal:

  1. choose $ a = 4 $ and $ b = 2 $ , so the new number is $ 3 $ , and the whiteboard contains $ [1, 3, 3] $ ;
  2. choose $ a = 3 $ and $ b = 3 $ , so the new number is $ 3 $ , and the whiteboard contains $ [1, 3] $ ;
  3. choose $ a = 1 $ and $ b = 3 $ , so the new number is $ 2 $ , and the whiteboard contains $ [2] $ .

It's easy to see that after $ n - 1 $ operations, there will be left only one number. Your goal is to minimize it.

输入格式

The first line contains one integer $ t $ ( $ 1 \le t \le 1000 $ ) — the number of test cases.

The only line of each test case contains one integer $ n $ ( $ 2 \le n \le 2 \cdot 10^5 $ ) — the number of integers written on the board initially.

It's guaranteed that the total sum of $ n $ over test cases doesn't exceed $ 2 \cdot 10^5 $ .

输出格式

For each test case, in the first line, print the minimum possible number left on the board after $ n - 1 $ operations. Each of the next $ n - 1 $ lines should contain two integers — numbers $ a $ and $ b $ chosen and erased in each operation.

样例 #1

样例输入 #1

1
4

样例输出 #1

2
2 4
3 3
3 1

D:

Paint the Array

题面翻译

$T$ 组数据。

对于每组数据,给定一个长度为 $n$ 的序列。

问是否存在一个数 $d$ ,将所有能被 $d$ 整除的数标记为红色,所有不能被 $d$ 整除的数标记为蓝色,使得序列中没有相邻的元素具有相同的颜色。

若存在,则输出任意一个满足条件的 $d$ ;若不存在,则输出 $0$ 。

题目描述

You are given an array $ a $ consisting of $ n $ positive integers. You have to choose a positive integer $ d $ and paint all elements into two colors. All elements which are divisible by $ d $ will be painted red, and all other elements will be painted blue.

The coloring is called beautiful if there are no pairs of adjacent elements with the same color in the array. Your task is to find any value of $ d $ which yields a beautiful coloring, or report that it is impossible.

输入格式

The first line contains a single integer $ t $ ( $ 1 \le t \le 1000 $ ) — the number of testcases.

The first line of each testcase contains one integer $ n $ ( $ 2 \le n \le 100 $ ) — the number of elements of the array.

The second line of each testcase contains $ n $ integers $ a_1, a_2, \dots, a_n $ ( $ 1 \le a_i \le 10^{18} $ ).

输出格式

For each testcase print a single integer. If there is no such value of $ d $ that yields a beautiful coloring, print $ 0 $ . Otherwise, print any suitable value of $ d $ ( $ 1 \le d \le 10^{18} $ ).

样例 #1

样例输入 #1

5
5
1 2 3 4 5
3
10 5 15
3
100 10 200
10
9 8 2 6 6 2 8 6 5 4
2
1 3

样例输出 #1

2
0
100
0
3

E:

Snow Walking Robot

题面翻译

有一个机器人,站在一个平面直角坐标系上,开始时他的坐标为$(0,0)$

给出一个指令序列$s$,它只由L,R,U,D 四个大写字母组成
若机器人当前坐标为$(x,y)$

  • 如果当前字母为 L,那么机器人就会向左移动到$x-1,y$
  • 如果当前字母为 R,那么机器人就会向右移动到$x+1,y$
  • 如果当前字母为 U,那么机器人就会向上移动到$x,y+1$
  • 如果当前字母为 D,那么机器人就会向下移动到$x,y-1$

如果一个坐标的点被走过了两次(除$(0,0)$外),那么机器人就会爆炸
一个操作序列合法,当且仅当中途机器人不会爆炸,并且满足指令序列结束时,机器人的坐标为$(0,0)$(也就是最后回到原点)
当然,空指令序列也是合法的

我们发现,所有的指令序列不一定都合法

给出一个指令序列$s$,你的任务是通过删除指令和重排序列,让指令序列合法,并且满足删除的指令数最小

输入格式

第一行一个整数$q$,表示有$q$组数据

接下来$q$行,每行一个字符串,代表一个指令串

输出格式

对于每组数据: 第一行一个整数,表示最多剩下多少条指令,使得指令序列合法,如果无论如何都不合法,输出$0$
第二行表示合法的指令序列,如果有多个合法序列,输出任意一个
如果无论如何都不合法,输出空的一行(注意那一行要空出来,详情见样例)

数据范围

$1 \le q \le 2\cdot 10^4$,$\sum|s| \le 10^5$
其中$|s|$为字符串$s$的长度
感谢 @_Wolverine 提供的翻译

题目描述

Recently you have bought a snow walking robot and brought it home. Suppose your home is a cell $ (0, 0) $ on an infinite grid.

You also have the sequence of instructions of this robot. It is written as the string $ s $ consisting of characters 'L', 'R', 'U' and 'D'. If the robot is in the cell $ (x, y) $ right now, he can move to one of the adjacent cells (depending on the current instruction).

  • If the current instruction is 'L', then the robot can move to the left to $ (x - 1, y) $ ;
  • if the current instruction is 'R', then the robot can move to the right to $ (x + 1, y) $ ;
  • if the current instruction is 'U', then the robot can move to the top to $ (x, y + 1) $ ;
  • if the current instruction is 'D', then the robot can move to the bottom to $ (x, y - 1) $ .

You've noticed the warning on the last page of the manual: if the robot visits some cell (except $ (0, 0) $ ) twice then it breaks.

So the sequence of instructions is valid if the robot starts in the cell $ (0, 0) $ , performs the given instructions, visits no cell other than $ (0, 0) $ two or more times and ends the path in the cell $ (0, 0) $ . Also cell $ (0, 0) $ should be visited at most two times: at the beginning and at the end (if the path is empty then it is visited only once). For example, the following sequences of instructions are considered valid: "UD", "RL", "UUURULLDDDDLDDRRUU", and the following are considered invalid: "U" (the endpoint is not $ (0, 0) $ ) and "UUDD" (the cell $ (0, 1) $ is visited twice).

The initial sequence of instructions, however, might be not valid. You don't want your robot to break so you decided to reprogram it in the following way: you will remove some (possibly, all or none) instructions from the initial sequence of instructions, then rearrange the remaining instructions as you wish and turn on your robot to move.

Your task is to remove as few instructions from the initial sequence as possible and rearrange the remaining ones so that the sequence is valid. Report the valid sequence of the maximum length you can obtain.

Note that you can choose any order of remaining instructions (you don't need to minimize the number of swaps or any other similar metric).

You have to answer $ q $ independent test cases.

输入格式

The first line of the input contains one integer $ q $ ( $ 1 \le q \le 2 \cdot 10^4 $ ) — the number of test cases.

The next $ q $ lines contain test cases. The $ i $ -th test case is given as the string $ s $ consisting of at least $ 1 $ and no more than $ 10^5 $ characters 'L', 'R', 'U' and 'D' — the initial sequence of instructions.

It is guaranteed that the sum of $ |s| $ (where $ |s| $ is the length of $ s $ ) does not exceed $ 10^5 $ over all test cases ( $ \sum |s| \le 10^5 $ ).

输出格式

For each test case print the answer on it. In the first line print the maximum number of remaining instructions. In the second line print the valid sequence of remaining instructions $ t $ the robot has to perform. The moves are performed from left to right in the order of the printed sequence. If there are several answers, you can print any. If the answer is $ 0 $ , you are allowed to print an empty line (but you can don't print it).

样例 #1

样例输入 #1

6
LRU
DURLDRUDRULRDURDDL
LRUDDLRUDRUL
LLLLRRRR
URDUR
LLL

样例输出 #1

2
LR
14
RUURDDDDLLLUUR
12
ULDDDRRRUULL
2
LR
2
UD
0

提示

There are only two possible answers in the first test case: "LR" and "RL".

The picture corresponding to the second test case:

Note that the direction of traverse does not matter Another correct answer to the third test case: "URDDLLLUURDR".

C题大赛-F-J

本文章由 WyOJ Shojo 从洛谷专栏拉取,原发布时间为 2024-02-28 13:56:38

F:

Yet Another Broken Keyboard

题面翻译

题目描述

$Norge$,找到了一个长度为$n$的字符串$s$($s$仅由小写英文字母构成),他想把这个字符串的所有$\frac{n(n+1)}{2}$个连续非空子串都打出来

可是,他发现他的键盘坏了,只能打出26字母中的$k$个
这$k$个字母分别为:$c_1,c_2,c_3,\dots ,c_k$

请求出用这个坏掉的键盘,最多能打出多少个字符串$s$的连续非空子串

输入格式

第一行两个整数 $n,k$ ,表示字符串$s$的长度,和能用字母的数量
第二行一个长度为$n$字符串$s$
第三行,$k$个由空格隔开的字母,表示键盘上没有坏掉的字母

输出格式

一行一个整数,表示用这个坏掉的键盘,最多能打出多少个字符串$s$的连续非空子串

数据范围

$1\leq n \le 2\cdot 10^5$,$1\leq k \le 26$
感谢 @_Wolverine 提供的翻译

题目描述

Recently, Norge found a string $ s = s_1 s_2 \ldots s_n $ consisting of $ n $ lowercase Latin letters. As an exercise to improve his typing speed, he decided to type all substrings of the string $ s $ . Yes, all $ \frac{n (n + 1)}{2} $ of them!

A substring of $ s $ is a non-empty string $ x = s[a \ldots b] = s_{a} s_{a + 1} \ldots s_{b} $ ( $ 1 \leq a \leq b \leq n $ ). For example, "auto" and "ton" are substrings of "automaton".

Shortly after the start of the exercise, Norge realized that his keyboard was broken, namely, he could use only $ k $ Latin letters $ c_1, c_2, \ldots, c_k $ out of $ 26 $ .

After that, Norge became interested in how many substrings of the string $ s $ he could still type using his broken keyboard. Help him to find this number.

输入格式

The first line contains two space-separated integers $ n $ and $ k $ ( $ 1 \leq n \leq 2 \cdot 10^5 $ , $ 1 \leq k \leq 26 $ ) — the length of the string $ s $ and the number of Latin letters still available on the keyboard.

The second line contains the string $ s $ consisting of exactly $ n $ lowercase Latin letters.

The third line contains $ k $ space-separated distinct lowercase Latin letters $ c_1, c_2, \ldots, c_k $ — the letters still available on the keyboard.

输出格式

Print a single number — the number of substrings of $ s $ that can be typed using only available letters $ c_1, c_2, \ldots, c_k $ .

样例 #1

样例输入 #1

7 2
abacaba
a b

样例输出 #1

12

样例 #2

样例输入 #2

10 3
sadfaasdda
f a d

样例输出 #2

21

样例 #3

样例输入 #3

7 1
aaaaaaa
b

样例输出 #3

0

提示

In the first example Norge can print substrings $ s[1\ldots2] $ , $ s[2\ldots3] $ , $ s[1\ldots3] $ , $ s[1\ldots1] $ , $ s[2\ldots2] $ , $ s[3\ldots3] $ , $ s[5\ldots6] $ , $ s[6\ldots7] $ , $ s[5\ldots7] $ , $ s[5\ldots5] $ , $ s[6\ldots6] $ , $ s[7\ldots7] $ .

G:

Ternary XOR

题面翻译

Ternary 数是只含有0、1、2的数。例如 $1022,11,21,2002$ 。

你会得到一个 ternary 数 $x$ 。它的左起第一位一定是 $2$ 。而其它位可以是 $0,1,2$ 。

让我们定义两个 $n$ 位的 ternary 数 $a$ 和 $b$ 之间的异或运算符号 $\bigodot$ 。 $a\bigodot b=c$ 。 $c$ 也是一个 $n$ 位的 ternary 数。 $c_i=(a_i+b_i)\%3$ 。例如, $10222\bigodot 11021=21210$ 。

给出几组 $c$ 与 $n$ ,求最小的 $max(a,b)$。 有多组数据。

题目描述

A number is ternary if it contains only digits $ 0 $ , $ 1 $ and $ 2 $ . For example, the following numbers are ternary: $ 1022 $ , $ 11 $ , $ 21 $ , $ 2002 $ .

You are given a long ternary number $ x $ . The first (leftmost) digit of $ x $ is guaranteed to be $ 2 $ , the other digits of $ x $ can be $ 0 $ , $ 1 $ or $ 2 $ .

Let's define the ternary XOR operation $ \odot $ of two ternary numbers $ a $ and $ b $ (both of length $ n $ ) as a number $ c = a \odot b $ of length $ n $ , where $ c_i = (a_i + b_i) \% 3 $ (where $ \% $ is modulo operation). In other words, add the corresponding digits and take the remainders of the sums when divided by $ 3 $ . For example, $ 10222 \odot 11021 = 21210 $ .

Your task is to find such ternary numbers $ a $ and $ b $ both of length $ n $ and both without leading zeros that $ a \odot b = x $ and $ max(a, b) $ is the minimum possible.

You have to answer $ t $ independent test cases.

输入格式

The first line of the input contains one integer $ t $ ( $ 1 \le t \le 10^4 $ ) — the number of test cases. Then $ t $ test cases follow. The first line of the test case contains one integer $ n $ ( $ 1 \le n \le 5 \cdot 10^4 $ ) — the length of $ x $ . The second line of the test case contains ternary number $ x $ consisting of $ n $ digits $ 0, 1 $ or $ 2 $ . It is guaranteed that the first digit of $ x $ is $ 2 $ . It is guaranteed that the sum of $ n $ over all test cases does not exceed $ 5 \cdot 10^4 $ ( $ \sum n \le 5 \cdot 10^4 $ ).

输出格式

For each test case, print the answer — two ternary integers $ a $ and $ b $ both of length $ n $ and both without leading zeros such that $ a \odot b = x $ and $ max(a, b) $ is the minimum possible. If there are several answers, you can print any.

样例 #1

样例输入 #1

4
5
22222
5
21211
1
2
9
220222021

样例输出 #1

11111
11111
11000
10211
1
1
110111011
110111010

H:

Array and Operations

题面翻译

给定 $n$ 个数和一个数 $k$,要求对这 $n$ 个数进行 $k$ 次操作,每次操作取出两个数 $a_i,a_j (i\neq j)$,并将 $\lfloor \frac{a_i}{a_j} \rfloor$ 加进得分中,其中 $\lfloor \frac{x}{y} \rfloor$ 为不超过 $\frac{x}{y}$ 的最大整数。

$k$ 次操作后,将剩下的 $n-2k$ 个数直接加入到得分中。

求最终得分的最小值。

题目描述

You are given an array $ a $ of $ n $ integers, and another integer $ k $ such that $ 2k \le n $ .

You have to perform exactly $ k $ operations with this array. In one operation, you have to choose two elements of the array (let them be $ a_i $ and $ a_j $ ; they can be equal or different, but their positions in the array must not be the same), remove them from the array, and add $ \lfloor \frac{a_i}{a_j} \rfloor $ to your score, where $ \lfloor \frac{x}{y} \rfloor $ is the maximum integer not exceeding $ \frac{x}{y} $ .

Initially, your score is $ 0 $ . After you perform exactly $ k $ operations, you add all the remaining elements of the array to the score.

Calculate the minimum possible score you can get.

输入格式

The first line of the input contains one integer $ t $ ( $ 1 \le t \le 500 $ ) — the number of test cases.

Each test case consists of two lines. The first line contains two integers $ n $ and $ k $ ( $ 1 \le n \le 100 $ ; $ 0 \le k \le \lfloor \frac{n}{2} \rfloor $ ).

The second line contains $ n $ integers $ a_1, a_2, \dots, a_n $ ( $ 1 \le a_i \le 2 \cdot 10^5 $ ).

输出格式

Print one integer — the minimum possible score you can get.

样例 #1

样例输入 #1

5
7 3
1 1 1 2 1 3 1
5 1
5 5 5 5 5
4 2
1 3 3 7
2 0
4 2
9 2
1 10 10 1 10 2 7 10 3

样例输出 #1

2
16
0
6
16

提示

Let's consider the example test.

In the first test case, one way to obtain a score of $ 2 $ is the following one:

  1. choose $ a_7 = 1 $ and $ a_4 = 2 $ for the operation; the score becomes $ 0 + \lfloor \frac{1}{2} \rfloor = 0 $ , the array becomes $ [1, 1, 1, 1, 3] $ ;
  2. choose $ a_1 = 1 $ and $ a_5 = 3 $ for the operation; the score becomes $ 0 + \lfloor \frac{1}{3} \rfloor = 0 $ , the array becomes $ [1, 1, 1] $ ;
  3. choose $ a_1 = 1 $ and $ a_2 = 1 $ for the operation; the score becomes $ 0 + \lfloor \frac{1}{1} \rfloor = 1 $ , the array becomes $ [1] $ ;
  4. add the remaining element $ 1 $ to the score, so the resulting score is $ 2 $ .

In the second test case, no matter which operations you choose, the resulting score is $ 16 $ .

In the third test case, one way to obtain a score of $ 0 $ is the following one:

  1. choose $ a_1 = 1 $ and $ a_2 = 3 $ for the operation; the score becomes $ 0 + \lfloor \frac{1}{3} \rfloor = 0 $ , the array becomes $ [3, 7] $ ;
  2. choose $ a_1 = 3 $ and $ a_2 = 7 $ for the operation; the score becomes $ 0 + \lfloor \frac{3}{7} \rfloor = 0 $ , the array becomes empty;
  3. the array is empty, so the score doesn't change anymore.

In the fourth test case, no operations can be performed, so the score is the sum of the elements of the array: $ 4 + 2 = 6 $ .

I:

Bricks and Bags

题面翻译

hhoppitree 有 $n$ 根木棍,其中第 $i$ 根木棍的长度为 $a_i$,他想要将它们放置在三个背包中,使得每个背包中至少有一根木棍

他的好朋友会从每个背包中选出一根木棍,假设从三个背包中取出的木棍的长度分别为 $x,y,z$,则他会送给 hhoppitree 一共 $|x-y|+|y-z|$ 瓶可乐,显然,他的朋友会最小化这个数的值

hhoppitree 想通过适当的分配,使得这个数的最小可能值最大,他想知道这个最大值是多少。

题目描述

There are $ n $ bricks numbered from $ 1 $ to $ n $ . Brick $ i $ has a weight of $ a_i $ .

Pak Chanek has $ 3 $ bags numbered from $ 1 $ to $ 3 $ that are initially empty. For each brick, Pak Chanek must put it into one of the bags. After this, each bag must contain at least one brick.

After Pak Chanek distributes the bricks, Bu Dengklek will take exactly one brick from each bag. Let $ w_j $ be the weight of the brick Bu Dengklek takes from bag $ j $ . The score is calculated as $ |w_1 - w_2| + |w_2 - w_3| $ , where $ |x| $ denotes the absolute value of $ x $ .

It is known that Bu Dengklek will take the bricks in such a way that minimises the score. What is the maximum possible final score if Pak Chanek distributes the bricks optimally?

输入格式

Each test contains multiple test cases. The first line contains an integer $ t $ ( $ 1 \leq t \leq 2 \cdot 10^4 $ ) — the number of test cases. The following lines contain the description of each test case.

The first line of each test case contains an integer $ n $ ( $ 3 \leq n \leq 2 \cdot 10^5 $ ) — the number of bricks.

The second line of each test case contains $ n $ integers $ a_1, a_2, \ldots, a_n $ ( $ 1 \leq a_i \leq 10^9 $ ) — the weights of the bricks.

It is guaranteed that the sum of $ n $ over all test cases does not exceed $ 2 \cdot 10^5 $ .

输出格式

For each test case, output a line containing an integer representing the maximum possible final score if Pak Chanek distributes the bricks optimally.

样例 #1

样例输入 #1

3
5
3 1 5 2 3
4
17 8 19 45
8
265 265 265 265 265 265 265 265

样例输出 #1

6
63
0

提示

In the first test case, one way of achieving a final score of $ 6 $ is to do the following:

  • Put bricks $ 1 $ , $ 4 $ , and $ 5 $ into bag $ 1 $ .
  • Put brick $ 3 $ into bag $ 2 $ .
  • Put brick $ 2 $ into bag $ 3 $ .

If Pak Chanek distributes the bricks that way, a way Bu Dengklek can take the bricks is:

  • Take brick $ 5 $ from bag $ 1 $ .
  • Take brick $ 3 $ from bag $ 2 $ .
  • Take brick $ 2 $ from bag $ 3 $ .

The score is $ |a_5 - a_3| + |a_3 - a_2| = |3 - 5| + |5 - 1| = 6 $ . It can be shown that Bu Dengklek cannot get a smaller score from this distribution.

It can be shown that there is no other distribution that results in a final score bigger than $ 6 $ .

J:

Binary Search

题面翻译

给定三个正整数 $n,x,pos$,请你求出满足以下条件的数组 $a$ 的个数:

  • 数组 $a$ 是正整数 1~$n$ 的一种排列,且 $a_{pos}=x$(下标从 $0$ 开始)

  • 对于数组 $a$ 运行如上代码(见图片,就是二分查找的模板),其返回值为true

请将答案对 $1e9+7$ 取模后输出。

翻译 by vectorwyx

题目描述

Andrey thinks he is truly a successful developer, but in reality he didn't know about the binary search algorithm until recently. After reading some literature Andrey understood that this algorithm allows to quickly find a certain number $ x $ in an array. For an array $ a $ indexed from zero, and an integer $ x $ the pseudocode of the algorithm is as follows:

Note that the elements of the array are indexed from zero, and the division is done in integers (rounding down).

Andrey read that the algorithm only works if the array is sorted. However, he found this statement untrue, because there certainly exist unsorted arrays for which the algorithm find $ x $ !

Andrey wants to write a letter to the book authors, but before doing that he must consider the permutations of size $ n $ such that the algorithm finds $ x $ in them. A permutation of size $ n $ is an array consisting of $ n $ distinct integers between $ 1 $ and $ n $ in arbitrary order.

Help Andrey and find the number of permutations of size $ n $ which contain $ x $ at position $ pos $ and for which the given implementation of the binary search algorithm finds $ x $ (returns true). As the result may be extremely large, print the remainder of its division by $ 10^9+7 $ .

输入格式

The only line of input contains integers $ n $ , $ x $ and $ pos $ ( $ 1 \le x \le n \le 1000 $ , $ 0 \le pos \le n - 1 $ ) — the required length of the permutation, the number to search, and the required position of that number, respectively.

输出格式

Print a single number — the remainder of the division of the number of valid permutations by $ 10^9+7 $ .

样例 #1

样例输入 #1

4 1 2

样例输出 #1

6

样例 #2

样例输入 #2

123 42 24

样例输出 #2

824071958

提示

All possible permutations in the first test case: $ (2, 3, 1, 4) $ , $ (2, 4, 1, 3) $ , $ (3, 2, 1, 4) $ , $ (3, 4, 1, 2) $ , $ (4, 2, 1, 3) $ , $ (4, 3, 1, 2) $ .

WFYZ-阶段测试20240330

本文章由 WyOJ Shojo 从洛谷专栏拉取,原发布时间为 2024-03-29 20:38:14

测试说明:

  • 0. 2023班做A-D,78级做B-F

  • 1.每人建立自己的名字命名的考试文件夹,里面放对应的A.CPP,B.CPP等(大小写均可)。

  • 2.不用文件输入输出。

  • 3.完成后通过极域学生端提交自己的试题文件夹。

A: 翻转求和

题目描述

给你一个$n$,让你求出从$1$到$n$的和,但是其中每当遇到一个数是$2$的次幂时,就要变加为减。例如输入$n=4$,那么计算算式为-1-2+3-4=-4,因为$1$是$2^0$,$2$是$2^1$,$4$是$2^2$。 该题目有$T$组数据。

输入格式

第一行给出数据组数 $ T $ ( $ 1<=T<=100 $ ),接下来$T$行,每行一个整数$n$( $ 1\leq n\leq10^{9} $ ).

输出格式

共 $ T $行,每行表示$ 1 $到$ n$在$2$的幂次取反后的和。

样例 #1

样例输入 #1

2
4
1000000000

样例输出 #1

-4
499999998352516354

数据范围

对于$100\%$的数据范围,$ 1<=T<=100 $ ,$1\leq n\leq10^{9} $

B 字符串循环移位

题目描述

给你一个字符串$s$,接着有$m$次循环移位。

循环移位的一个操作就是将$s$的最后一个字符移动到第一个字符的位置,并且将所有其他的字符向右移动一个位置。

例如,$s='abacaba'$,查询是$L_1=3,R_1=6,K_1=1$,那么答案是$’abbacaa’$。循环移位的过程是从$s$第三个位置到第六个位置$’acab’$,循环$1$次,把$b$移到第一位,其他往后移一位,就是$’baca’$,替换之前的$’acab’$,之后如果我们再做处理$L_2=1,R_2=4,K_2=2$,那么答案就变$’baabcaa’$。循环移位的过程是:首先从第一个位置到第四个位置$’abba’$,第一次通过移位得到$’aabb’$,第二次就得到$’baab’$,替换之前的$’abba’$。

输入格式

第一行一个字符串$s$,$(1 \leq |s|\leq10000)$,$s$全是小写字母;

第二行一个整数$m$,有$m$次操作;

接下来有$m$行,包含三个整数$L_i,R_i, K_i(1<=L_i<=R_i<=|s|,K_i<=1000000)$。

输出格式

输出经过$m$个操作后的$s$。

样例 #1

样例输入 #1

abacaba
2
3 6 1
1 4 2

样例输出 #1

baabcaa

数据范围

对于$100\%$的数据范围, $ 1<=m<=300 $, $ 1<=l_{i}<=r_{i}<=|s|,1<=k_{i}<=1000000 $

C 参观博物馆

题目描述

小容到博物馆里看画,博物馆是一个$n·m $的区域$,'.'表示可以走的房间,'*'表示墙。

每个房间都是矩形,最多可能有四面墙。每面墙上贴有一幅画,每个四联通的 ' .'区域是一个展馆,小容参观了$k$个展馆。现在给出小容的位置,求他在每个展馆最多看到多少幅画?

输入格式

第一行$3$个整数 $ n $ , $ m $ 和 $ k $ ,分别表示博物馆区域 和小容可能出现位置的个数.

接下来 $ n $行,每行 $ m $ 个 '.', '\*' 表示博物馆的布局。

接下来 $ k $ 行,每行包含两个整数 $ x $ 和 $ y $ , $ 1\leq x \leq n,1\leq y \leq m $ ) 表示小容所在的位置.

输出格式

输出 $ k $ 个整数 ,表示小容在每个展厅可能看到最多所少幅画。

样例 #1

样例输入 #1

5 6 3
******
*..*.*
******
*....*
******
2 2
2 5
4 3

样例输出 #1

6
4
10

样例 #2

样例输入 #2

4 4 1
****
*..*
*.**
****
3 2

样例输出 #2

8

样例解释 #2

第三行第三列的分别在不同方向的房间上各挂一幅画。所以总共是$8$。

数据范围

对于$100 \%$的数据, $ 3 \leq n,m\leq1000,1\leq k \leq min(n·m,100000) $

D 开灯

题目描述

农夫约翰试图让奶牛玩智力玩具来保持它们的敏锐。谷仓里的灯是较大的玩具之一。$N (2 \le N \le 10^5)$ 个牛栏编号为 $1 \ldots N$,每个牛栏上面都有一盏灯。起初所有的灯都关着。

共有 $M$ 次操作,分为两种。

  1. 指定一个区间 $[S_i,E_i]$,然后改变编号在这个区间内的灯的状态(把开着的灯关上,关着的灯打开);
  2. 指定一个区间 $[S_i,E_i]$,要求你输出这个区间内有多少盏灯是打开的。

输入格式

第 $1$ 行: 用空格隔开的两个整数 $N$ 和 $M$,$N$ 是灯数。

第 $2\ldots M+1$ 行: 每行表示一个操作, 有三个用空格分开的整数: 指令号, $S_i$ 和 $E_i$。

若指令号为 $0$,则表示改变 $[S_i,E_i]$ 区间内的灯的状态(把开着的灯关上,关着的灯打开)。

若指令号为 $1$,则表示输出 $[S_i,E_i]$ 这个区间内有多少盏灯是打开的。

输出格式

样例 #1

样例输入 #1

4 5
0 1 2
0 2 4
1 2 3
0 2 4
1 1 4

样例输出 #1

1
2

提示

数据点编号 $N$ $M$
$1\sim 2$ $\le 100$ $\le 100$
$3\sim 4$ $\le 1000$ $\le 1000$
$5\sim 6$ $\le 10000$ $\le 10000$
$7\sim 8$ $\le 10^5$ $\le 100$
$9\sim 10$ $\le 100$ $\le 10^5$
$11\sim 12$ $\le 1000$ $\le 10^5$
$13\sim 14$ $\le 10^5$ $\le 1000$
$15\sim 16$ $\le 10000$ $\le 10000$
$17\sim 18$ $\le 10$ $\le 10^5$
$19\sim 20$ $\le 2000$ $\le 10^6$

E 苹果树

题面翻译

题目描述

给你一棵有 $n$ 个节点的苹果树,下标从 $0$ 开始。

第 $i$ 个节点可以为白色或黑色,其中至少有一个节点为黑色。

现在你可以从中删去若干条边,使得剩下的每个部分恰有一个黑色节点。

问有多少种符合条件的删边方法,答案对 $10^9+7$ 取模。

输入格式

第一行一个整数 $n(1\leq n\leq 10^5)$,表示节点个数。

接下来一行 $n-1$ 个整数 $(p_0,p_1,\cdots,p_{n-2},0\leq p_i\leq i)$,表示树中有一条连接节点 $p_i$ 和节点 $i+1$ 的边。

接下来一行 $n$ 个整数 $(x_0,x_1,\cdots,x_{n-1},0\leq x_i\leq 1)$,若 $x_i$ 为 $1$,则节点 $i$ 为黑色,否则为白色。

输出格式

第一行一个整数,表示符合条件的删边方法的方案数对 $10^9+7$ 取模后的值。

样例 #1

样例输入 #1

3
0 0
0 1 1

样例输出 #1

2

样例 #2

样例输入 #2

6
0 1 1 0 4
1 1 0 0 1 0

样例输出 #2

1

样例 #3

样例输入 #3

10
0 1 2 1 4 4 4 0 8
0 0 0 1 0 1 1 0 0 1

样例输出 #3

27

数据范围

对于$100\%$的数据范围,$ 2\leq n\leq 10^{5} $ ,$ (0\leq k<n) $

$(p_0,p_1,\cdots,p_{n-2},0\leq p_i\leq i)$

F 吃巧克力

题目描述

你有一块长方形的巧克力,这块巧克力共有$n*m$小块。你想吃$k$小块巧克力,因此你也许需要掰开这块巧克力。

在每一次操作中你可以把任意一块矩形形状的巧克力掰成两块矩形形状的巧克力。你只能沿着巧克力小块之间的分割线掰开巧克力——可以沿着水平方向或是竖直方向掰开。掰开巧克力的花费等于分割线长度的平方。

例如,如果你有一块$23$的巧克力,那么你可以沿着水平方向掰从而得到两块$13$的巧克力,这次操作的花费即为$3^2=9$。或者你也可以沿着竖直方向掰从而得到一块$21$的巧克力和一块$22$的巧克力,这次操作的花费即为$2^2=4$。

对于每一个给出的$n,m$和$k$,计算出最小花费。你可以用多块巧克力凑出$k$小块巧克力。剩余的巧克力可以不是完整的一块。

输入格式

输入数据的第一行包括1个整数$t(1<=t<=40910)$,表示数据组数。

接下来的$t$行每一行都包含$3$个整数$n,m$和$k(1<=n,m<=30,1<=k<=min(n*m,50))$,其意义见上文。

输出格式

输出t行,分别表示每一组数据的最小花费。

样例 #1

样例输入 #1

4
2 2 1
2 2 3
2 2 2
2 2 4

样例输出 #1

5
5
4
0

提示

在样例一的第1行这组数据情况下一共需要进行$2$次操作: 1.把$22$的巧克力掰成两块$21$的巧克力,花费为$2^2=4$;

2.把$21$的巧克力掰成两块$11$的巧克力,花费为$1^2=1$。

在样例一的第2行这组数据情况下操作步骤同上。

数据范围

对于$100\%$的数据范围,$1<=t<=40910,1<=n,m<=30,1<=k<=min(n*m,50)$

OIer对拍的使用

本文章由 WyOJ Shojo 从洛谷专栏拉取,原发布时间为 2024-03-31 10:06:52

1.何为对拍?

对拍:通过暴力程序去验证优化后的程序是否正确,称之为对拍(优化后的程序不知道正确性,但是可以通过暴力程序去验证优化后的程序是否正确)

2.什么时候用对拍?

  • a.没有测试数据的情况。
  • b.可以网络评测,但交上去后不知道自己错在哪里的的情况。 比如ABC347的C题。很多同学错了几遍也找不到错误的原因。

3.怎么写对拍?

需要准备的原材料:

  • a.待检验的程序。
  • b.一个保证正确的暴力程序
  • c.数据生成器

先生成小数据,大数据不利于查错,小数据无错的情况,再试试边界数据等特殊情况。都过的话再测试大数据。

  • d.对拍程序

把这四个程序都编译完成,生成EXE文件。

4.实战演练

例题:ABC347C

  • a.待检验的程序。zhyt的C题代码,总是错一个点。文件名abc347c.CPP
#include <bits\/stdc++.h>
using namespace std;
#define TRACE 1
#define tcout TRACE && cout

#define int long long
int n,a,b;
int x[1000005];
signed main()
{
     cin>>n>>a>>b;
     for(int i=1;i<=n;i++)
     {
     	cin>>x[i];
     	x[i]%=(a+b);
     	\/*if(x[i]==0)
     	{
     		x[i]=a+b;
		 }*\/
	 }
	 sort(x+1,x+n+1);
	 if(x[n]-x[1]+1<=a){
	 	cout<<"Yes"; 	 
	 }	
	 else{	
	 	cout<<"No";
	 }
	return 0;
}

  • b.一个保证正确的暴力程序,文件名abc347c-baoli.cpp
\/\/暴力思路,枚举当前是星期几,挨个算那些日期是不是在周末。
#include <bits\/stdc++.h>
using namespace std;
#define TRACE 1
#define tcout TRACE && cout

#define int long long
int n,a,b;
int x[1000005];
bool check(int k){
	for(int i=1;i<=n;i++){
		if((k+x[i])%(a+b)>=a)return false;
	}
	return true;
}
signed main()
{
     cin>>n>>a>>b;
     for(int i=1;i<=n;i++)
     {
     	cin>>x[i];
     	x[i]--;
     	x[i]%=(a+b);
	 }
	 for(int i=0;i<a+b;i++){
	 	if(check(i)){
	 		cout<<"Yes";
	 		return 0;
		 }
	 }
	 cout<<"No";
	
	return 0;
}

  • c.数据生成器
#include<bits\/stdc++.h>
using namespace std;

int main() {
	srand((int)time(NULL));
	int n=rand()%4+2;
	int a=rand()%5+1,b=rand()%5+1;
	cout<<n<<" "<<a<<" "<<b<<endl;
	for(int i=1;i<=n;i++){
		cout<<rand()%(a+b)+1<<" "; 
	}	
}
  • d.对拍程序
#include<cstdio>
#include<cstdlib>
#include<ctime>

int main()
{   long s,t;
    while(1){
        system("cls");
        do{
            system("makedata.exe> try.in"); \/\/data是数据生成程序
            s=clock();
            system("abc347c.exe< try.in > try1.out");  \/\/a是要交的程序
            t=clock();
            system("abc347c-baoli.exe< try.in > try2.out");  \/\/b是正确的程序
            if(system("fc try1.out try2.out > nul"))
                break;
            else printf("AC time: %ldms\n",t-s);
        }while(1);
        printf("WA time: %ldms\n",t-s);  \/\/运行时间 
        system("fc try1.out try2.out");
        system("pause>nul");
    }
    return 0;
}

运行检验

  • 本次出现的结果如下:
AC time: 367ms
AC time: 254ms
AC time: 129ms
AC time: 131ms
AC time: 181ms
AC time: 129ms
WA time: 136ms
正在比较文件 try1.out 和 TRY2.OUT
***** try1.out
No
***** TRY2.OUT
Yes
*****


  • 找出错误数据:然后我们打开try.in文件看看
2 3 4
7 6

错误调试

现在可以发现0和6的差值>=a,但也是可以都安排在休假范围内的。,错误的原因是要转圈看是否可以都在假期范围内。

  • $x_1,x_2,...x_n$,这时候$x_n-x_1+1$
  • $x_2,x_3,...x_n,x_1$,这时候$x1-x_2+1$,排序后会$\leq 0$,因此需要再加上$a+b$.

变换到一般话的情况

  • $x_{i+1},...x_n,x_1,...x_i$,这时候判断 $x_i-x_{i+1}+1+a+b \leq a$ 那你会修改自己的程序了吗?快来试试吧。

修改后的代码

#include <bits\/stdc++.h>

using namespace std;

#define TRACE 1
#define tcout TRACE && cout

#define int long long
int n,a,b;
int x[1000005];
signed main()
{
     cin>>n>>a>>b;
     for(int i=1;i<=n;i++)
     {
     	cin>>x[i];
     	x[i]%=(a+b);
	 }
	 sort(x+1,x+n+1);
	 if(x[n]-x[1]+1<=a){
	 	cout<<"Yes";
	 	 return 0;
	 }
	 else {
	 	for(int i=1;i<n;i++)
	 		if(x[i]+a+b-x[i+1]+1<=a){ 
	 		cout<<"Yes";
	 		 return 0;
		 }
	 }		
	cout<<"No";
	
	return 0;
}

P1496 火烧赤壁-离散化

本文章由 WyOJ Shojo 从洛谷专栏拉取,原发布时间为 2024-04-17 14:52:38

校门外的树扩展

离散化学习:oiwiki

方法一:离散化后用校门外的树方法




#include<bits\/stdc++.h>
using namespace std;
const int N=2e5+5;
int n;
int x[N<<1];
int a[N],b[N],c[N];
int main()
{
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
	{
		scanf("%d%d",&a[i],&b[i]);
		x[2*i-1]=a[i];
		x[2*i]=b[i];
	}
	sort(x+1,x+1+2*n);
	int m=unique(x+1,x+2*n+1)-x-1;
	for(int i=1;i<=n;i++)
	{
		int L=lower_bound(x+1,x+m+1,a[i])-x;
		int R=lower_bound(x+1,x+m+1,b[i])-x;
		for(int j=L;j<R;j++)c[j]+=1;

	}
	int h=0,t=0,ans=0;
	for(int i=1;i<=m;i++)
	{
		if(!c[i-1]&&c[i])ans+=1;
		if(c[i]&&c[i-1])  ans+=x[i]-x[i-1];
		else if(c[i-1]&&!c[i]) ans+=x[i]-x[i-1]-1;
	}
	cout<<ans;

	return 0;
 }

方法二 :利用前缀和,区间修改,再求前缀和

#include<bits\/stdc++.h>
using namespace std;
const int N=2e5+5;
int n;
int x[N<<1];
int a[N],b[N],c[N];
int main()
{
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
	{
		scanf("%d%d",&a[i],&b[i]);
		x[2*i-1]=a[i];
		x[2*i]=b[i];
	}
	sort(x+1,x+1+2*n);
	int m=unique(x+1,x+2*n+1)-x-1;
	for(int i=1;i<=n;i++)
	{
		int L=lower_bound(x+1,x+m+1,a[i])-x;
		int R=lower_bound(x+1,x+m+1,b[i])-x;
	\/\/	for(int j=L;j<R;j++)c[j]+=1;
		 c[L]++,c[R]--;

	}

	int h=0,t=0,ans=0;
	for(int i=1;i<=m;i++)
	{   c[i]+=c[i-1];
		if(!c[i-1]&&c[i])ans+=1;
		if(c[i]&&c[i-1])  ans+=x[i]-x[i-1];
		else if(c[i-1]&&!c[i]) ans+=x[i]-x[i-1]-1;
	}

	cout<<ans;

	return 0;
 }

最后的处理还可以只记录起点和终点

int h=0,t=0,ans=0;
	for(int i=1;i<=m;i++)
	{   c[i]+=c[i-1];
		if(!c[i-1]&&c[i])h=x[i];

		else if(c[i-1]&&!c[i]) t=x[i],ans+=t-h;
	}

【智龙】-题解训练

本文章由 WyOJ Shojo 从洛谷专栏拉取,原发布时间为 2024-04-30 13:51:29

【智龙】解题报告专项练习

| 姓名 | 专栏 | 作业题解 | | -----------: | -----------: | -----------: | | lxn| | | zrl | 专栏地址 | P2669 [NOIP2015 普及组] 金币 | | opec | 专栏地址 | CF1941E Rudolf and k Bridges | | zyt | |P8783统计子矩阵 | | why | |P8783 统计子矩阵 | | gzq | zhuan'lan'd | abc351d | | lwh | | p8783 | | lhb | |abc351d | | yzh| | | | zyh | | ABC351DGrid and Magnet | | lmh | |P8783统计子矩阵 | | xhl | |P8783统计子矩阵 | | dqy | | p8783 | | cck | 我的专栏 | P8783统计子矩阵 | | qc | | P7714 | | glrq | |P8783统计子矩阵题解 | | wct | |P8783统计子矩阵题解 | | fwx | | | | fcx | | | | hyx | |P8783统计子矩阵 | | zyz | | ABC347C | | syr | | | | zzh | | | | gjy | |CF1955A Yogurt Sale | | wxl | | CF1956A |

样例:

P3368 【模板】树状数组 2

本文章由 WyOJ Shojo 从洛谷专栏拉取,原发布时间为 2023-11-26 17:47:58

线段树 tzt模板,区间修改,单点查询,懒惰标记

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
struct tree {
    int lc,rc,sum,tag;
} a[1000005];
int n,m,t,ans,A[500005],x,y,w,q;
void pushup(int u) {
    a[u].sum=a[a[u].lc].sum+a[a[u].rc].sum;
}
void pushdown(int u,int l,int r) {
    int mid=(l+r)\/2;
    a[a[u].lc].sum+=(mid-l+1)*a[u].tag;
    a[a[u].lc].tag+=a[u].tag;
    a[a[u].rc].sum+=(r-mid)*a[u].tag;
    a[a[u].rc].tag+=a[u].tag;
    a[u].tag=0;
}
void build(int u,int l,int r) {
    if(l==r) {
        a[u].sum=A[l];
        return;
    }
    int mid=(l+r)\/2;
    a[u].lc=++t;
    build(a[u].lc,l,mid);
    a[u].rc=++t;
    build(a[u].rc,mid+1,r);
    pushup(u);
}
void update(int u,int l,int r,int ll,int rr,int w) {\/\/区间更新 
    if(ll<=l&&r<=rr) {
        a[u].sum+=(r-l+1)*w;
        a[u].tag+=w;
        return;
    }
    int mid=(l+r)\/2;
    pushdown(u,l,r);\/\/只要往下走,就把懒惰标记捎下去
    if(ll<=mid)update(a[u].lc,l,mid,ll,rr,w);
    if(rr>mid)update(a[u].rc,mid+1,r,ll,rr,w);
    pushup(u);
}
int query(int u,int l,int r,int ll,int rr) {\/\/区间查询 
    int ans=0; 
    if(ll<=l&&r<=rr)
        return ans+=a[u].sum;
    int mid=(l+r)\/2;
    pushdown(u,l,r);\/\/只要往下走,就把懒惰标记捎下去
    if(ll<=mid)ans+=query(a[u].lc,l,mid,ll,rr);
    if(rr>mid)ans+=query(a[u].rc,mid+1,r,ll,rr);
    return ans;
}
int query_p(int u,int l,int r,int ll) {\/\/单点查询 
    int ans=0; 
    if(ll==l&&r==ll)
        return ans+=a[u].sum;
    int mid=(l+r)\/2;
    pushdown(u,l,r);\/\/只要往下走,就把懒惰标记捎下去
    if(ll<=mid)ans=query_p(a[u].lc,l,mid,ll);
    else ans=query_p(a[u].rc,mid+1,r,ll);
    return ans;
}
int main() {
    scanf("%d%d",&n,&m);
    for(int i=1; i<=n; i++)scanf("%d",&A[i]);
    t=1;
    build(1,1,n);
    for(int i=1; i<=m; i++) {
        scanf("%d%d",&q,&x);
        if(q==1) {
            scanf("%d%d",&y,&w);
            update(1,1,n,x,y,w);
        } else {	
            int ans=query_p(1,1,n,x);
            printf("%d\n",ans);
        }
    }
    return 0;
}

鸡蛋的硬度

本文章由 WyOJ Shojo 从洛谷专栏拉取,原发布时间为 2023-12-01 09:26:18

鸡蛋的硬度

题目描述

给你 k 枚相同的鸡蛋,并可以使用一栋从第 1 层到第 n 层共有 n 层楼的建筑。

已知存在楼层 f ,满足 0 <= f <= n ,任何从 高于 f 的楼层落下的鸡蛋都会碎,从 f 楼层或比它低的楼层落下的鸡蛋都不会破。

每次操作,你可以取一枚没有碎的鸡蛋并把它从任一楼层 x 扔下(满足 1 <= x <= n)。如果鸡蛋碎了,你就不能再次使用它。如果某枚鸡蛋扔下后没有摔碎,则可以在之后的操作中 重复使用 这枚鸡蛋。

请你计算并返回要确定 f 确切的值 的 最小操作次数 是多少?

算法分析

状态:很明显,就是当前拥有的鸡蛋数 K 和需要测试的楼层数 N。随着测试的进行,鸡蛋个数可能减少,楼层的搜索范围会减小,这就是状态的变化。

选择:其实就是去选择哪层楼扔鸡蛋。回顾刚才的线性扫描和二分思路,二分查找每次选择到楼层区间的中间去扔鸡蛋,而线性扫描选择一层层向上测试。不同的选择会造成状态的转移。

现在明确了「状态」和「选择」,动态规划的基本思路就形成了:肯定是个二维的 dp 数组或者带有两个状态参数的 dp 函数来表示状态转移;外加一个 for 循环来遍历所有选择,择最优的选择更新状态。

定义dp函数:dp(K, N)表示当有K个鸡蛋面对N层楼时,至少需要dp(K, N)次操作才能得到答案

状态转移:

如果鸡蛋碎了,那么鸡蛋的个数 K 应该减一,搜索的楼层区间应该从 [1..N] 变为 [1..i-1] 共 i-1 层楼;

如果鸡蛋没碎,那么鸡蛋的个数 K 不变,搜索的楼层区间应该从 [1..N] 变为 [i+1..N] 共 N-i 层楼。

$$

dp[K][N]=MIN(MAX(dp[K-1][i-1],dp[K][N-i])+1),0<i \leq n $$

所以算法的总时间复杂度是 $O(K*N^2)$, 空间复杂度$ O(KN)$。

优化1:二分查找

首先简述一下原始动态规划的思路:

1、暴力穷举尝试在所有楼层 1 <= i <= N 扔鸡蛋,每次选择尝试次数最少的那一层;

2、每次扔鸡蛋有两种可能,要么碎,要么没碎;

3、如果鸡蛋碎了,F 应该在第 i 层下面,否则,F 应该在第 i 层上面;

4、鸡蛋是碎了还是没碎,取决于哪种情况下尝试次数更多,因为我们想求的是最坏情况下的结果。

核心的状态转移方程: $$

dp[K][N]=MIN(MAX(dp[K-1][i-1]+dp[K][N-i]+1)),0<i \leq n $$

如果能够理解这个状态转移方程,那么就很容易理解二分查找的优化思路。

首先我们根据$ dp(K, N) $数组的定义(有 K 个鸡蛋面对 N 层楼,最少需要扔几次),很容易知道 K 固定时,这个函数随着 N 的增加一定是单调递增的,无论你策略多聪明,楼层增加测试次数一定要增加。

那么注意 dp(K - 1, i - 1) 和 dp(K, N - i) 这两个函数,其中 i 是从 1 到 N 单增的,如果我们固定 K 和 N,把这两个函数看做关于 i 的函数,前者随着 i 的增加应该也是单调递增的,而后者随着 i 的增加应该是单调递减的:

优化2 决策单调性

两部分的关系

方法二涉及决策单调性,是竞赛中的考点。这里我们不会叙述 何为决策单调性 以及 如何根据决策单调性写出优化的动态规划,而是仅指出决策单调性的存在性。

思路

我们重新写下方法一中的状态转移方程 决策单调性分析

作者:力扣官方题解 链接:https://leetcode.cn/problems/super-egg-drop/solutions/197163/ji-dan-diao-luo-by-leetcode-solution-2/ 来源:力扣(LeetCode) 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

#include<iostream>
#include<string.h>
using namespace std;
int f[209][209],st[209][209];
const int inf=0x3f3f3f3f;
int work(int n,int m) {
	for(int i=1; i<=n; i++)f[i][1]=i,st[i][1]=i-1,st[1][i]=1,f[1][i]=1;
	for(int j=2; j<=m; j++) {
		int k=1;\/\/每次的决策点从1层楼开始,随着鸡蛋的数增加,决策楼层数间隔增加。
			for(int i=2; i<=n; i++) {
				f[i][j]=inf;
				if(f[i-k][j]>f[k-1][j-1])k++;
					f[i][j]=min(f[i][j],f[k-1][j-1]+1);
			}
			
	}
	return f[n][m];
}
int main() {
	int n,m;
	while(cin>>n>>m) {
		f[0][0]=0;
		for(int i=1; i<=n; i++)f[i][1]=i,f[1][i]=1,f[0][i]=0;
		cout<<work(n,m)<<endl;
	}

}

方法四,状态重定义

题目不是给你 K 鸡蛋,N 层楼,让你求最坏情况下最少的测试次数 m 吗? while 循环结束的条件是 dp[K][m] == N, 也就是给你 K 个鸡蛋,测试 m 次,正在进行第m次测试。 最坏情况下最多能测试 N 层楼。

 1 2 3             (4)             5 6 7 8
 
dp(k-1,m-1)       在这儿扔1次      dp(k,m-1) 测试

可以测试出的最多楼层数 可以测试出的最多楼层数

1、无论你在哪层楼扔鸡蛋,鸡蛋只可能摔碎或者没摔碎,碎了的话就测楼下,没碎的话就测楼上。

2、无论你上楼还是下楼,总的楼层数 = 楼上的楼层数 + 楼下的楼层数 + 1(当前这层楼)。

根据这个特点,可以写出下面的状态转移方程: $$ dp[k][m] = dp[k][m - 1] + dp[k - 1][m - 1] + 1 $$

$dp[k][m - 1] $就是楼上的楼层数,因为鸡蛋个数 k 不变,也就是鸡蛋没碎,扔鸡蛋次数 m 减一;

$dp[k - 1][m - 1] $就是楼下的楼层数,因为鸡蛋个数 k 减一,也就是鸡蛋碎了,同时扔鸡蛋次数 m 减一。

PS:这个 m 为什么要减一而不是加一?之前定义得很清楚,这个 m 是一个允许的次数上界,而不是扔了几次。

原文链接:https://blog.csdn.net/qq_39144436/article/details/123617917

参考:https://leetcode.cn/problems/super-egg-drop/solutions/44427/ji-ben-dong-tai-gui-hua-jie-fa-by-labuladong/

官方题解:https://leetcode.cn/problems/super-egg-drop/solutions/197163/ji-dan-diao-luo-by-leetcode-solution-2/

共 90 篇博客