链接
题意:给出两个数,问x可不可以通过减去质数得到y
思路:唯一分解定理
#include<bits/stdc++.h>
using namespace std;
#define int long long
signed main()
{
int T;
cin >> T;
while (T--) {
int a, b;
cin >> a >> b;
if (a - 1 != b) {cout << "YES" << endl;}
else cout << "NO" << endl;
}
return 0;
}
链接
题意:一个水平的坐标轴,怪兽都在原点右边,若使得怪物到达原点右边,则怪兽死亡。可以开炮
①如果怪物在炮弹上,怪物死亡
②怪物在炮弹左边,怪物左移给定的r个单位
③怪物在炮弹右边,怪物右移给定的r个单位
当怪物在原点左边(包括原点)也算死亡
思路:贪心的去看,我们发现怪物在右边是无效操作,所以我们从最远的怪物开始打,一直往前打到怪物全死就行
#include<bits/stdc++.h>
using namespace std;
#define int long long
int st[100010];
signed main()
{
int T;
cin >> T;
while (T--) {
int n, r;
cin >> n >> r;
vector<int> vec;
for (int i = 1; i <= n; i++) {
int x;
cin >> x;
if (!st[x]) vec.push_back(x);
st[x] = 1;
}
sort(vec.begin(), vec.end(), greater<int>());
int ans = 0;
for (int i = 0; i < vec.size(); i++) {
if (vec[i] <= ans * r) break;
ans++;
}
cout << ans << endl;
for (int i = 0; i < vec.size(); i++) st[vec[i]] = 0;
}
return 0;
}
链接
题意:右一些连续的高台
1
→
1
0
18
1 \to 10^{18}
1→1018,现在你在最高处
h
[
1
]
h[1]
h[1],你的任务是到1,现在只有一部分高台可以站人,但是你每次落下的时候,会把下一个高台变成相反的状态,你落脚的地方不能和你下落的地方落差超过2,现在你要改变一些高台的初始状态,让你可以安全的到1,问最少操作多少次
思路:只用看这一个的上一个和上上个是不是差一就行了。。差一就要从上一个花费一个代价,不然直接就从上上个转移就行了。。
#include<bits/stdc++.h>
using namespace std;
const int N = 2e5+10;
int h[N], dp[N];
int main()
{
int T;
cin >> T;
while (T--) {
int st, n;
cin >> st >> n;
for (int i = 1; i <= n; i++) {
cin >> h[i]; h[i + 1] = 0;
dp[i] = 0;
}
for (int i = n - 1; i >= 1; i--) {
if (h[i + 2] + 1 != h[i + 1]) dp[i] = dp[i + 1] + 1;
else dp[i] = dp[i + 2];
}
cout << dp[1] << endl;
}
return 0;
}
链接
题意:给出字符串,好子串的定义是,子串每一个字符都包含在这个子串的一个回文子串中,问有多少个好子串,这个子串只由AB构成
思路:我们可以发现,其实只要有2个相同的字符,他们中间字符的就都是在好子串中比如
A
.
.
.
.
.
.
A
A......A
A......A,特别的
B
A
A
A
A
A
BAAAAA
BAAAAA这种不是好子串,所以我们只需要记录上一个A和上一个B的位置就可以了,现在是A,则从上一个A开始往前的子串全是好子串,并且上一个B在上一个A前面的时候要减1,上面已经讨论过了,B同理
#include<bits/stdc++.h>
using namespace std;
#define int long long
char s[300010];
signed main()
{
int n;
cin >> n;
cin >> (s + 1);
int a = 0, lasta = 0, b = 0, lastb = 0, ans = 0;
for (int i = 1; i <= n; i++) {
if (s[i] == 'A') {
ans += lasta;
if (lastb < lasta && lastb) ans--;
lasta = i;
}
if (s[i] == 'B') {
ans += lastb;
if (lasta < lastb && lasta) ans--;
lastb = i;
}
}cout << ans << endl;
return 0;
}
链接
题意:给出目标字符串,你要设计一个键盘,他的字母排成一排,要求最少需要在键盘移动多少次可以输入这个字符串
思路:我们可以状压键盘,所以我们转移的时候需要的东西就是每新加入一个字母的时候他的贡献,我们统计相邻的字母记为
c
n
t
[
i
]
[
j
]
cnt[i][j]
cnt[i][j],新加入的代价就是
c
n
t
[
i
]
[
j
]
∗
(
p
o
s
i
−
p
o
s
j
)
=
c
n
t
[
i
]
[
j
]
∗
p
o
s
i
−
c
n
t
[
j
]
[
i
]
∗
p
o
s
j
cnt[i][j] * (pos_i-pos_j)=cnt[i][j]*pos_i-cnt[j][i]*pos_j
cnt[i][j]∗(posi−posj)=cnt[i][j]∗posi−cnt[j][i]∗posj我们把
c
n
t
[
i
]
[
j
]
∗
p
o
s
i
cnt[i][j]*pos_i
cnt[i][j]∗posi看成
t
m
p
tmp
tmp,所以我们对于每一个代价,直接加上他的
t
m
p
tmp
tmp,就行了,对于已经加入键盘的,我们的
t
m
p
tmp
tmp就是
c
n
t
[
i
]
[
j
]
∗
n
u
m
cnt[i][j]*num
cnt[i][j]∗num,否则就减去tmp,num是已经加入键盘的字母的个数,他多余的会抵消掉
#include<bits/stdc++.h>
using namespace std;
//#define int long long
int dp[2000010], cnt[30][30];
int main()
{
int n, m;
cin >> n >> m;
string s;
cin >> s;
for (int i = 0; i < n - 1; i++) {
cnt[s[i] - 'a'][s[i + 1] - 'a']++, cnt[s[i + 1] - 'a'][s[i] - 'a']++;
}
for (int i = 0; i < m; i++) cnt[i][i] = 0;
int len = (1 << m) - 1;
memset(dp, 0x3f, sizeof (dp));dp[0] = 0;
for (int i = 0; i <= len; i++) {
int num = 0;
for (int j = 0; j < m; j++) if ((1 << j) & i) num++;
for (int j = 0; j < m; j++) {
if (((1 << j) & i) == 0) {
int sum = 0;
for (int k = 0; k < m; k++) {
if((1 << k) & i)sum += cnt[j][k] * num;
else sum -= cnt[k][j] * num;
}
dp[i | (1 << j)] = min(dp[i] + sum, dp[i | (1 << j)]);
}
}
}
cout << dp[len];
return 0;
}
链接
题意:给出一颗树,你要给每个点设置
[
l
,
r
]
[l,r]
[l,r],好树的定义是如果两个节点之间的区间可以包含,就在他们之间链接一条边,最后和原树子树一样,问最大的好树有多大
思路:可以发现,除了树最左边和最右边的点,其他的点不可以存在儿子节点,因为这样就会和上面的区间形成交集,破坏子树,所以我们只需要求一个树的直径就行了,然后统计直径链最大的点的度数和就行了
#include<bits/stdc++.h>
using namespace std;
const int N = 3e5+10;
int head[N], idx;
struct Edge{int to, nxt;}e[N << 1];
void add(int u, int v) {e[++idx].to = v, e[idx].nxt = head[u], head[u] = idx;}
int du[N];
int st, ans, n;
void dfs(int u, int fa, int d)
{
if (d > ans) {ans = d, st = u;}
for (int i = head[u]; i; i = e[i].nxt) {
int v = e[i].to;
if (v == fa) continue;
dfs(v, u, d + du[v]);
}
}
int main()
{
int T;
cin >> T;
while (T--) {
cin >> n;
for (int i = 1; i <= n; i++) head[i] = 0, du[i] = -1; idx = 0;
for (int i = 1; i < n; i++) {
int u, v;
cin >> u >> v;
add(u, v); add(v, u);
du[u]++, du[v]++;
}
ans = -1;
dfs(1, -1, du[1]);
dfs(st, -1, du[st]);
cout << ans + 2 << endl;
}
return 0;
}