由于OJ上还没有题没法测试,不保证代码准确,但是算法思想肯定是对的,等可以交的话通过后这句会删掉。
其他的题以后补。
题目大意为给定 A,B
。需要判定是否存在一组数 l , r
,使得区间内有 A 个奇数 B 个偶数。范围为1e18
。
是个水题。
很明显奇数偶数最多差一个,否则不是连续的。所以当 A,B
相差小于1 时输出 YES
,否则为 NO
。
需要注意 A,B
同为 0 时输出 NO
,并且测试样例较多需要用scanf
或者开输入输出挂
//水
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define TI() \
int T; \
cin >> T; \
while (T--)
int main()
{
TI()
{
ll a, b;
scanf("%lld%lld", &a, &b);
if (abs(a - b) > 1 || !(a || b)) {
printf("NO\n");
} else {
printf("YES\n");
}
}
return 0;
}
题目大意为Bob想通过一条有n
扇门的路,每经过一扇门需要一把钥匙,购买一把钥匙花费为1
,门的种类不同也需要不同种钥匙,他可以在任何时间购买任一种钥匙,但最多携带k
种钥匙。
开始考虑分段,即从当前往后考虑k
种门,经过这k道门的花费为k-x
,x
为此时拥有的钥匙中,和之后k种门种类相同的个数,即若当前拥有钥匙{1,2,3}
,后k种为{2,3,4}
,则只需丢掉钥匙1,购买钥匙4即可,答案为3-2=1
;
然后就WA到自闭。
最后快结束的时候ljg想到一个样例为{1,2,3,4,5,3,2,1}, k=3
,发现这样跑下来答案为7,但是有更优答案为6。
所以这算法是假的!!!
之后换了贪心的思路 (也是官方题解),每次需要买钥匙的时候,丢掉距离当前位置最远使用的钥匙就可以了,比如上面样例在拥有钥匙{1,2,3}
时碰到门4,判断出下一次用1是最远的,则丢掉1;拥有{2,3,4}
碰到门5,判断出4之后不再使用 (距离记为inf) 丢掉4。
注意记录的下标总体最多 1e5
,但需要动态存储否则会超内存。
// 思维+队列
//代码写好了补
//input
/*
3
6 2
1 2 3 1 3 4
10 3
1 2 3 5 1 3 2 4 2 1
5 3
1 2 3 4 5 3 2 1
*/
//output
/*
4
6
6
*/
题目大意为判定输入{A,C,W}
构成的字符串是否合法,合法条件为:WA不能相连且AC至少出现一次 。
初见开始在想数位DP(因为前几天一直在看),后来发现是一个简单的递推;
状态 A1[i],C1[i],W1[i] 分别表示以 A,C,W 结尾长度为i且不存在WA的字符串的个数
状态 A2[i],C2[i],W2[i] 分别表示以 A,C,W 结尾长度为i且不存在WA和AC的字符串的个数
初始状态:
A1[1]=C1[1]=W1[1]=A2[1]=C2[1]=W2[1]=1;
转移公式为:
A1[i]= A1[i-1]+C1[i-1] ;
C1[i]= A1[i-1]+C1[i-1]+W[i-1];
W1[i]= A1[i-1]+C1[i-1]+W[i-1];
A2[i]= A2[i-1]+C2[i-1] ;
C2[i]= C2[i-1]+W2[i-1];
W2[i]= A2[i-1]+C2[i-1]+W2[i-1];
答案为长度为n,不存在WA且存在AC的状态数。
二者相减即可:
ans=A1[n]+C1[n]+W1[n]-(A2[n]+C2[n]+W2[n]);
O(n)跑一遍取模输出就可以了。
注意实现的时候不需要建6个数组来存,只需要12个变量重复赋值即可。
//递推
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;;
const int mod = (1e9 + 7);
int main()
{
int n;
ll a, _a, c, _c, w, _w;
ll a1, _a1, c1, _c1, w1, _w1;
while (cin >> n) {
a = _a = c = _c = w = _w = 1;
a1 = _a1 = c1 = _c1 = w1 = _w1 = 1;
for (int i = 2; i <= n; i++) {
a = (_a + _c) % mod;
c = (_a + _c + _w) % mod;
w = (_a + _c + _w) % mod;
a1 = (_a1 + _c1) % mod;
c1 = (_c1 + _w1) % mod;
w1 = (_a1 + _c1 + _w1) % mod;
_a = a, _c = c, _w = w;
_a1 = a1, _c1 = c1, _w1 = w1;
} //循环使用节省内存;
cout << ((a + c + w) % mod - (a1 + c1 + w1) % mod + mod) % mod << endl;
}
return 0;
}
//input
/*
10
100
*/
//output
/*
11869
807464439
*/
题目大意为有一堆糖果,每个糖果有一个快乐值,小明想可以进行三步操作:
1.将一个糖果的值变为[-100,100]
任意 和原值不同 的值;
2.将所有糖果按顺序放,规则为每次只能放到最上或者最下;
3.计算总值,规则为奇加偶减;
按顺序给定初始值,求结果最大为多少。
样例1:1 2
则将1变为-100 , 2 放在第一位,答案为 2-(-100)=102
分析:
1.每次放到最上最下,那么每两个数必定有一个在奇数位一个在偶数位。设两个值为 a,b
,对这两个数来说,摆放结果最大为|a-b|
;
2.考虑改变a的值:a在奇数位,改变后结果为100-b
;a在偶数位,结果为100+b
;则无论a在何处,最大结果为100+|b|
,所以对某一对来说,改变a的收益为100+|b|-|a-b|
,所以需要改变这一对中绝对值小的那个值。要使收益最大化,需要将每一对按照收益排序,选择最合适的进行改变。
所以建立结构体储存值 (|a|<=|b|) ,输入时累加,编cmp函数用sort排序,或者标记一下最大收益的对,最后加上收益就是答案了。
需要注意,如果每一对都是{100,-100}的情况,因为要变成不同的,最后答案需要-1;
复杂度是 O(n) 级别的。
官方题解坐太后排没看清,但是说复杂度 O(n^3) 推测应该是DP 。
//贪心+思维
#include <bits/stdc++.h>
using namespace std;
struct Pro {
int a, b, mabs;
} p[55];
bool cmp(Pro A, Pro B)
{
int ans1 = 100 + abs(A.b) - A.mabs;
int ans2 = 100 + abs(B.b) - B.mabs;
return ans1 > ans2;
}
int main()
{
int n;
while (cin >> n) {
int ans = 0;
bool flag = true;
for (int i = 0; i < n / 2; i++) {
cin >> p[i].a >> p[i].b;
if (abs(p[i].a) > abs(p[i].b)) {
swap(p[i].a, p[i].b);
}
p[i].mabs = abs(p[i].a - p[i].b);
ans += p[i].mabs;
if ((p[i].mabs) != 200) {
flag = false;
}
}
sort(p, p + n / 2, cmp);
ans += (100 + abs(p[0].b) - (p[0].mabs));
if (flag)
ans -= 1;
cout << ans << endl;
}
return 0;
}
//input
/*
2 1 2
2 -1 -2
2 -1 2
4 100 -100 -100 100
4 100 100 100 -100
*/
//output
/*
102
102
399
400
*/