A:如果负数是偶数个,不需要改变
否则把其中一个数变成0即可
#include<bits/stdc++.h>
using namespace std;
const int N = 1e6+10,mod=998244353;
#define int long long
typedef long long LL;
typedef pair<int, int> PII;
typedef unsigned long long ULL;
const long long inf=1e17;
using node=tuple<int,int,int,int>;
int n,m,k;
int gcd(int a, int b) // 欧几里得算法
{
return b ? gcd(b, a % b) : a;
}
int lcm(int a,int b){
return a*b/gcd(a,b);
}
int a[N];
void solve()
{
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i];
int mx=0;
bool ok=true;
int cnt=0;
for(int i=1;i<=n;i++)
{
if(a[i]==0){
cout<<0<<"\n";
return ;
}
if(a[i]<0) ok=false,cnt++;
}
if(cnt&1){
cout<<0<<"\n";
return ;
}
else{
cout<<1<<"\n";
cout<<1<<" "<<"0\n";
}
//cout<<max(mx,mn)<<"\n";
}
signed main()
{
cin.tie(0);cout.tie(0);ios::sync_with_stdio(0);
int t=1;
cin>>t;
while(t--) solve();
}
B:
操作题先想操作的性质
可以手玩一下
可以发现操作如果前面有两个字母固定不能删了,那么后面就全都不能操作了,都是完整的一个后缀了
即最后格式肯定是 前面一个字母+一个后缀
所以对于每个后缀求前面有多少个不同的字母就行了
注意后缀为空的时候也是要算的
一个字母加空后缀也是合法的
且因为每个后缀长度不同贡献不同
#include<bits/stdc++.h>
using namespace std;
const int N = 1e6+10,mod=998244353;
typedef long long LL;
typedef pair<int, int> PII;
typedef unsigned long long ULL;
const long long inf=1e17;
using node=tuple<int,int,int,int>;
int n,m,k;
int a[N],b[N];
void solve()
{
string s;cin>>n>>s;
set<char> st;
int res=0,now=0;
for(auto x:s)
{
res+=st.size();
st.insert(x);
}
res+=st.size();
cout<<res<<"\n";
}
signed main()
{
cin.tie(0);cout.tie(0);ios::sync_with_stdio(0);
int t=1;
cin>>t;
while(t--) solve();
}
C:
操作题先想操作
如果重置了数组,且因为b[i]都大于0
即肯定有一个前缀加一
因为变成全0后,增加一个后缀,不论怎么加,因为他要求的是递增的,所以最多只会让一个位置下标等于数值
所以如果充值了,最好的贡献是加一个前缀再加一分 让a[1]=1满足就行
所以直接枚举哪个位置开始操作第二个位置就行了,
我是直接暴力到1e5了,差不多是,因为会存在一些位置
比如 [0,0,0,0,0,1,2,3,4,5,6]
[10]
这个情况,所以我的建议是直接拉满到1e5
实际最多需要4000估计就肯定操作第二个操作了3
#include<bits/stdc++.h>
using namespace std;
const int N = 1e6+10,mod=998244353;
typedef long long LL;
typedef pair<int, int> PII;
typedef unsigned long long ULL;
const long long inf=1e17;
using node=tuple<int,int,int,int>;
int n,m,k;
int a[N],b[N];
void solve()
{
int d;
cin>>n>>k>>d;
for(int i=1;i<=n;i++) cin>>a[i];
for(int i=0;i<k;i++) cin>>b[i];
int res=0;
for(int i=1;i<=min(d,100000);i++)
{
int cnt=max(0,(d-i)/2);
int c=0;
for(int j=1;j<=n;j++)
{
if(a[j]==j) c++;
}
res=max(res,c+cnt);
for(int j=1;j<=b[(i-1)%k];j++){
a[j]++;
}
// cout<<c<<"\n";
}
cout<<res<<"\n";
}
signed main()
{
cin.tie(0);cout.tie(0);ios::sync_with_stdio(0);
int t=1;
cin>>t;
while(t--) solve();
}
D:
记住b[i]是连续的!!!!!!
分开计算两个贡献
自己内部 a[i]里面不同b[i]的贡献
和不同a[i]里面的贡献
第一个贡献就是b[i]的逆序对*n
第二个贡献比较麻烦
上上周的牛客小白赛最后一题你们可以做一做
就是如果乘2^19已经大于了a[i]里面的全部数,那么后面的贡献就全是
(k-18)*(k-19)/2%mod*i
就是因为a[i]乘2^19肯定比其他数都大,所以剩下的k-18个数都会大于全部a[i]
第一个循环是找向上第一个跨越长度的
第二个循环是找向下跨越长度的
0.0算了放弃解释了思密达
Codeforces Round 917 (A-D)讲解_哔哩哔哩_bilibili
看这个视频吧
#include<bits/stdc++.h>
using namespace std;
const int N = 1e6+10,mod=998244353;
#define int long long
typedef long long LL;
typedef pair<int, int> PII;
typedef unsigned long long ULL;
const long long inf=1e17;
using node=tuple<int,int,int,int>;
int n,m,k;
int a[N],b[N];
class BitTree {
public:
vector<int> tree;
int n;
BitTree(int _n) : n(_n) {
tree.resize(n+1);
fill(tree.begin(),tree.end(),0);
}
inline int lowbit(int x) { return x&-x; }
inline void Modify(int x,int v) {
for(;x;x-=lowbit(x)) tree[x]+=v;
}
inline int q(int x) {
int ret=0;
for(;x<=n;x+=lowbit(x)) ret+=tree[x];
return ret;
}
inline int Query(int l,int r) {
return q(r)-q(l-1);
}
};
int qmi(int a, int k, int p) // 求a^k mod p
{
int res = 1 % p;
while (k)
{
if (k & 1) res = (LL)res * a % p;
a = (LL)a * a % p;
k >>= 1;
}
return res;
}
void solve()
{
int n,k;
cin>>n>>k;
vector<int> p(n),q(k);
BitTree T1(k),T2(2*n-1);
for(int i=0;i<n;++i)cin>>p[i];
for(int i=0;i<k;++i)cin>>q[i],++q[i];
int ans=0,sum=0;
for(int i=0;i<k;++i){
sum+=T1.q(q[i]);
T1.Modify(q[i],1);
}
ans=sum%mod*n%mod;
for(int i=0;i<n;++i){
for(int j=0;j<min(k,19ll);++j){
ans=(ans+1ll*T2.q(min(2ll*n,(LL)p[i]<<j))*(k-j))%mod;
}
for(int j=1;j<min(k,19ll);++j){
ans=(ans+1ll*T2.q((p[i]>>j)+1)*(k-j))%mod;
}
if(k>19)ans=(ans+1ll*(k-18)*(k-19)/2%mod*i)%mod;
T2.Modify(p[i],1);
}
cout<<ans<<'\n';
}
signed main()
{
cin.tie(0);cout.tie(0);ios::sync_with_stdio(0);
int t=1;
cin>>t;
while(t--) solve();
}