A
按题意模拟
#include <bits/stdc++.h>
#define int long long
#define ull unsigned long long
int use[105];
void paralysis(){
int k,q;
std::cin>>k>>q;
std::vector<int> a(k+1);
for (int i=1;i<=k;i++){
std::cin>>a[i];
}
while (q--){
int n;
std::cin>>n;
int len=0,flag=1;
for (int i=1;i<=n;i++){
use[++len]=i;
}
while (flag){
flag=0;
for (int i=1;i<=k;i++){
if (a[i]>len) break;
use[a[i]]=0;
flag=1;
}
int temp=len;
len=0;
for (int i=1;i<=temp;i++){
if (!use[i]) continue;
use[++len]=use[i];
// std::cout<<use[len]<<" ";
}
}
std::cout<<len<<" ";
}
std::cout<<"\n";
}
signed main(){
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
std::cout.tie(nullptr);
int T=1;
std::cin>>T;
while (T--){
paralysis();
}
return 0;
}
B
只有自己手牌中出现两次的牌能得分
#include <bits/stdc++.h>
#define int long long
#define ull unsigned long long
void paralysis(){
int n;
std::cin>>n;
int ans=0;
std::vector<int> cnt(n+1);
for (int i=1;i<=n;i++){
int x;
std::cin>>x;
cnt[x]++;
if (cnt[x]==2){
ans++;
}
}
std::cout<<ans<<"\n";
}
signed main(){
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
std::cout.tie(nullptr);
int T=1;
std::cin>>T;
while (T--){
paralysis();
}
return 0;
}
C
每次操作序列都为12…n,从最后一行开始,行列交替操作
#include <bits/stdc++.h>
#define int long long
#define ull unsigned long long
using namespace std;
void paralysis(){
int n;
std::cin>>n;
std::vector<std::vector<int>> a(n+1,std::vector<int>(n+1));
int sum=0;
for (int i=n;i>=1;i--){
for (int j=1;j<=n;j++){
sum+=j-a[i][j];
a[i][j]=j;
sum+=j-a[j][i];
a[j][i]=j;
}
}
std::cout<<sum<<" "<<2*n<<"\n";
for (int i=n;i>=1;i--){
std::cout<<"1 "<<i<<" ";
for (int j=1;j<=n;j++){
std::cout<<j<<" ";
}
std::cout<<"\n";
std::cout<<"2 "<<i<<" ";
for (int j=1;j<=n;j++){
std::cout<<j<<" ";
}
std::cout<<"\n";
}
}
signed main(){
ios::sync_with_stdio(false);
cin.tie(nullptr);
cout.tie(nullptr);
int T=1;
cin>>T;
while (T--){
paralysis();
}
return 0;
}
D
长度为
n
n
n,每个位置的上限是
n
n
n,然后从小的数据手玩
0->1
00->01->22
000->001->022->020->021->333
发现存在类似递归的方法
那么对于某个区间,要么转换成
n
∗
n
n*n
n∗n,要么不变
做区间dp求最大,记录一下需要操作的区间
// LUOGU_RID: 155892430
#include <bits/stdc++.h>
#define int long long
#define ull unsigned long long
using namespace std;
void paralysis(){
int n;
cin>>n;
vector<int> sum(n+1);
vector<vector<int>> f(n+1,vector<int>(n+1)),pos(n+1,vector<int>(n+1));
for (int i=1;i<=n;i++){
cin>>sum[i];
sum[i]+=sum[i-1];
}
for (int len=1;len<=n;len++){
for (int i=1;i+len-1<=n;i++){
int j=i+len-1;
pos[i][j]=-1;
f[i][j]=sum[j]-sum[i-1];
if (len*len>f[i][j]){
pos[i][j]=0;
f[i][j]=len*len;
}
for (int k=i;k<j;k++){
if (f[i][k]+f[k+1][j]>f[i][j]){
pos[i][j]=k;
f[i][j]=f[i][k]+f[k+1][j];
}
}
}
}
vector<pair<int,int>> ans;
function<void(int,int,int)> write=[&](int x,int top,int now){
if (now==1){
ans.push_back({x,x});
return;
}
for (int i=now-1;i>=1;i--){
write(x,top,i);
for (int j=1;j<i;j++){
ans.push_back({x+j-1,x+j-1});
}
}
ans.push_back({x,x+now-1});
};
function<void(int,int)> dfs=[&](int l,int r){
if (pos[l][r]==-1){
return;
}
if (pos[l][r]==0){
for (int i=l;i<=r;i++){
if (sum[i]-sum[i-1]){
ans.push_back({i,i});
}
}
write(l,r-l+1,r-l+1);
return;
}
dfs(l,pos[l][r]);
dfs(pos[l][r]+1,r);
};
dfs(1,n);
cout<<f[1][n]<<" "<<ans.size()<<"\n";
for (auto [x,y]:ans){
cout<<x<<" "<<y<<"\n";
}
}
signed main(){
ios::sync_with_stdio(false);
cin.tie(nullptr);
cout.tie(nullptr);
int T=1;
// cin>>T;
while (T--){
paralysis();
}
return 0;
}
E
简单版本,全局考虑,最后存活的怪物旁边不会有怪物
再往前推,场数少时,最后存活的怪物右边有怪物。
假设某个状态存活的怪物右边的右边有怪物,即
x
−
>
y
−
>
z
x->y->z
x−>y−>z(血量)
考虑
z
z
z 最大血量能撑多久,计算得
(
y
−
x
)
+
(
y
−
2
∗
x
)
+
.
.
.
+
(
y
%
x
)
(y-x)+(y-2*x)+...+(y\%x)
(y−x)+(y−2∗x)+...+(y%x),大致求出是轮数是
y
/
x
y/x
y/x级别的,最大就是
y
y
y级别的。
总结一下就是经过最多
y
y
y轮,造成
y
∗
y
y*y
y∗y级别的伤害,反推得最多经过
z
\sqrt z
z轮
所以模拟跑几千轮,最后血量大于0的连通块个数即为答案
困难版同样的分析方法,可得跑 a 1 3 a^{1 \over 3} a31轮后,会出现 x − > y − > z x->y->z x−>y−>z的连通块,然后分析一下 y y y 和 z z z 谁先死,其它做法和简单版本相同
// LUOGU_RID: 155896350
#include <bits/stdc++.h>
#define ll long long
#define ull unsigned long long
using namespace std;
void paralysis(){
int n;
cin>>n;
vector<int> a(n+1);
for (int i=1;i<=n;i++){
cin>>a[i];
}
for (int l=0;l<=1500;l++){
for (int i=1;i<=n;i++){
a[i]=max(0,a[i]);
if (a[i]>0){
a[i%n+1]-=a[i];
}
}
}
vector<int> ans;
for (int i=1;i<=n;i++){
int x=i+1,y=i+2;
while (x>n) x-=n;
while (y>n) y-=n;
if (a[i]>0&&a[x]>0&&a[y]>0){
ll res=1LL*(a[x]-a[i]+a[x]%a[i])*(1+(a[x]-a[i]-a[x]%a[i])/a[i])/2;
if (i==n) res+=a[x];
if (res<a[y]){
}else{
a[y]=0;
}
a[x]=0;
}
}
for (int i=1;i<=n;i++){
if (a[i]>0&&a[i%n+1]>0){
a[i%n+1]=0;
}
}
for (int i=1;i<=n;i++){
if (a[i]>0){
ans.emplace_back(i);
}
}
cout<<ans.size()<<"\n";
for (auto x:ans){
cout<<x<<" ";
}
cout<<"\n";
}
int main(){
ios::sync_with_stdio(false);
cin.tie(nullptr);
cout.tie(nullptr);
int T=1;
cin>>T;
while (T--){
paralysis();
}
return 0;
}