A. Long Comparison
题目:传送门
题意:分别给出两个数字和这两个数字后面又多少个0,请问这两个组合之后的数相比谁大谁小,输出’>’, ‘<‘或’=’;
解题思路:直接暴力模拟,先看组合后的数长度位数,再从前往后循环模拟,我用string存储前面的数字,当长度一样时,往两个字符串后面加上相同位数的’0‘,避免越界;
AC代码:
void solve(){
int x, y;
string s, c;
cin>>s>>x;
cin>>c>>y;
int l1 = s.length()+x, l2 = c.length()+y;
if(l1 == l2){
int flag = 0;
s+="0000000";
c+="0000000";
for(int i = 0; i<min(s.length(), c.length()); i++){
if(s[i]>c[i]){
flag = 1;
break;
}
if(s[i]<c[i]){
flag = -1;
break;
}
}
if(flag == 0){
puts("=");
}
else if(flag == 1){
puts(">");
}
else {
puts("<");
}
return;
}
else if(l1>l2){
puts(">");
return;
}
else{
puts("<");
return;
}
return;
}
int main()
{
int t;
scanf("%d", &t);
while(t--){
solve();
}
return 0;
}
B. Absent Remainder
题目:传送门
题意:一道思路特别简单的题目,我第一眼还没看出来QAQ,对于t组测试样例,给出长度为n的数组a,找出n/2(下取整)个对数(x,y),满足:
1、x != y;
2、x和y都属于数组a中的数;
3、x%y的值不属于数组a;
解题思路:x%y的值一定小于y,直接找到a数组中最小的数,往后面找n/2个数和他凑对输出就行了,第一眼还没看出这个思路,真的是太憨憨了;
AC代码:
const int N = 2e5+5;
int a[N];
int st[1000006];
bool cmp(int x, int y){
return x>y;
}
void solve(){
int n;
scanf("%d", &n);
for(int i = 1; i<=n; i++) scanf("%d", &a[i]);
sort(a+1, a+n+1);
int cnt = 0;
for(int i = 2; i<=n/2+1; i++){
printf("%d %d\n", a[i], a[1]);
}
return;
}
int main()
{
int t;
scanf("%d", &t);
while(t--){
solve();
}
return 0;
}
C. Poisoned Dagger
题目:传送门
题意:勇者斗巨龙,对于t组测试样例,每次给出一个数组a和一个值h,h表示巨龙的血量,数组a表示勇者每到第ai的时间,就会给巨龙施加一个流血debuff,流血debuff为每秒使得巨龙掉一滴血,连续掉k秒,此debuff不叠加,也就是说,若上一个debuff未结束,又给巨龙施加流血debuff,那么上一个debuff状态结束,现在要求勇者能将巨龙打死的最小的k是多少;
解题思路:讲真的感觉这题比第二题好想,翻译出来后就可以看出用的wf算法——二分;经典的二分答案题目,对于k的值做二分答案,判断函数模拟当前k的值能否杀死巨龙,找到最小的k;
AC代码:
const int N = 105;
ll a[N];
ll n, h;
bool check(ll x){
ll res = 0;
for(int i = 2; i<=n; i++){
ll ans = a[i]-a[i-1];
res+=min(ans, x);
}
res+=x;
if(res>=h) return true;
else return false;
}
void solve(){
scanf("%lld%lld", &n, &h);
for(int i = 1; i<=n; i++) scanf("%lld", &a[i]);
sort(a+1, a+n+1);
ll l = 1, r = 1e18;
while(l<r){
ll mid = l+r>>1;
if(check(mid)) r = mid;
else l = mid+1;
}
printf("%lld\n", l);
return;
}
int main()
{
int t;
scanf("%d", &t);
while(t--){
solve();
}
return 0;
}
D. MEX Sequences
题目:传送门
题意:定义MEX(x1……xk)是 x1~xk中未出现的最小非负整数,对于t组测试样例,每组给出一个数组,求有多少个满足条件的子序列——条件:
|xi-MEX(x1…xi)|<=1
例如: i=1 时满足 |x1-MEX(x1)|<=1,i=2 时满足|x1-MEX(x1)|<=1和 |x2-MEX(x1,x2)|<=1
解题思路:看这个数据范围,找子序列,是个dp没跑了(可能也有更高深的算法),根据题目描述,构成满足条件的子序列仅有两种情况:
1、从0开始序列单调不递减连续:
2、前面从0开始单调不递减连续,后面序列为若干个x,若干个x+2,若干个x……
类似于:0,1,1,2,4,4,2,2,4,4
根据这两种情况推出状态转移方程;
对于情况1(比较好写):
dp1[0] = 1;
对于数组每个值x, dp1[x] += dp1[x](前面有x-1的序列)+dp[x-1](没有x-1的序列);
对于情况2:
对于数组每个值x,dp2[x] = 2, dp2[x+2] = 2,每个x和x+2都可以选择放与不放;
并且当x大于1的时候dp2[x] += dp1[x-2]**结合的时候;
AC代码:
typedef long long ll;
const int mod = 998244353;
const int N = 5e5+5;
ll dp[2][N];
void solve()
{
int n;
scanf("%d", &n);
dp[0][0] = 1;
int x;
for(int i=1; i<=n; i++){
scanf("%d", &x); x++;
dp[0][x] = (dp[0][x]*2ll+dp[0][x-1])%mod;
dp[1][x] = dp[1][x]*2ll%mod;
dp[1][x+2] = dp[1][x+2]*2ll%mod;
if(x>=2) dp[1][x] = (dp[1][x]+dp[0][x-2])%mod;
}
ll sum = 0;
for(int i=1; i<=n+1; i++) sum+=dp[0][i]+dp[1][i], sum%=mod;
printf("%lld\n", sum);
for(int i = 0; i<=n+1; i++) dp[0][i] = 0, dp[1][i] = 0;
return;
}
int main()
{
int t;
scanf("%d", &t);
while(t--){
solve();
}
return 0;
}
完结撒花!