Codeforces Round 1042 (Div. 3) (A - G)
A. Lever
只需要考虑每个 \(a_i~>~b_i\) 的数,计算差值累加即可
点击查看代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
using pii=pair<int,int>;
using ll = long long;
using ull = unsigned long long;
const ll inf = 1e18;
const int mod = 998244353;
void solve(){
int n;
cin>>n;
vector<int> a(n+1),b(n+1);
int ans=0;
for(int i=1;i<=n;i++){
cin>>a[i];
}
for(int i=1;i<=n;i++){
cin>>b[i];
if(a[i]>b[i]) ans+=a[i]-b[i];
}
cout<<ans+1<<endl;
}
signed main(){
ios::sync_with_stdio(0);
cin.tie(0);
int ct=1;
cin>>ct;
while(ct--){
solve();
}
return 0;
}
B. Alternating Series
对于奇数:-1 3 -1 3 -1
对于偶数:-1 3 -1 3 -1 3 -1 2 (注意最后一个可以是 \(2\))
点击查看代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
using pii=pair<int,int>;
using ll = long long;
using ull = unsigned long long;
const ll inf = 1e18;
const int mod = 998244353;
void solve(){
int n;
cin>>n;
if(n==2){
cout<<"-1 2"<<endl;
return;
}
vector<int> a(n+1);
for(int i=1;i<=n;i+=2){
a[i]=-1;
}
for(int i=2;i<=n;i+=2){
a[i]=3;
}
if((n%2)==0) a[n]=2;
for(int i=1;i<=n;i++){
cout<<a[i]<<" ";
}
cout<<endl;
}
signed main(){
ios::sync_with_stdio(0);
cin.tie(0);
int ct=1;
cin>>ct;
while(ct--){
solve();
}
return 0;
}
C. Make it Equal
原题目等价于对于 \(S,T\) 数组中的每个数 \(val\), 可以变成 \(val\%k\) 或 \(k~-~val\%k\)
所以可以将 \(S,T\) 中的每个数变成 \(pair(min(vak\%k,~k~-~val\%k),max(val\%k,~k~-~val\%k))\) 的形式,然会分别排序
判断排序后的 \(pair\) 是否一一对应即可
点击查看代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
using pii=pair<int,int>;
using ll = long long;
using ull = unsigned long long;
const ll inf = 1e18;
const int mod = 998244353;
void solve(){
int n,k;
cin>>n>>k;
vector<pii> s(n+1),t(n+1);
for(int i=1;i<=n;i++){
int val;
cin>>val;
val%=k;
int tmp=k-val;
if(val>tmp) swap(val,tmp);
s[i]={val,tmp};
}
for(int i=1;i<=n;i++){
int val;
cin>>val;
val%=k;
int tmp=k-val;
if(val>tmp) swap(val,tmp);
t[i]={val,tmp};
}
sort(s.begin()+1,s.end());
sort(t.begin()+1,t.end());
for(int i=1;i<=n;i++){
if(s[i].first==t[i].first && s[i].second==t[i].second) continue;
// cout<<s[i].first<<" "<<s[i].second<<" "<<t[i].first<<" "<<t[i].second<<endl;
cout<<"NO\n";
return;
}
cout<<"YES\n";
}
signed main(){
ios::sync_with_stdio(0);
cin.tie(0);
int ct=1;
cin>>ct;
while(ct--){
solve();
}
return 0;
}
D. Arboris Contractio
显然变成一个菊花图是最优情况 (特判 \(n=2\))
所以我们要选一个节点作为菊花图的中心节点 \(u\),然后每次操作选择 \(u\) 和一个叶节点 \(v\)
而如果 \(v\) 是 \(u\) 的子节点则无需操作
所以找一个子节点是叶节点的个数最多节点作为 \(u\), 然后每次操作选择不是 \(u\) 子节点的叶节点即可
点击查看代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
using pii=pair<int,int>;
using ll = long long;
using ull = unsigned long long;
const ll inf = 1e18;
const int mod = 998244353;
void solve(){
int n;
cin>>n;
vector<vector<int>> g(n+1);
for(int i=1;i<n;i++){
int u,v;
cin>>u>>v;
g[u].push_back(v);
g[v].push_back(u);
}
if(n==2 || n==3){
cout<<0<<endl;
return;
}
int ye=0;
for(int i=1;i<=n;i++){
if(g[i].size()==1) ye++;
}
int mx=0;
for(int i=1;i<=n;i++){
int cnt=0;
for(auto v:g[i]){
if(g[v].size()==1) cnt++;
}
mx=max(mx,cnt);
}
cout<<ye-mx<<endl;
}
signed main(){
ios::sync_with_stdio(0);
cin.tie(0);
int ct=1;
cin>>ct;
while(ct--){
solve();
}
return 0;
}
E. Adjacent XOR
对于 \(a[i]\), 只有两种可能的变化
-
和没有变化过的 \(a[i+1]\) 进行异或,这一步可以直接在原数组上从前往后计算一边,如果能变换成 \(b[i]\) 就直接变过去
-
和变化过的 \(a[i+1]\) 进行异或,这一步从后往前做,如果 \(a[i+1]\) 已经变成 \(b[i+1]\) 则可以变化
点击查看代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
using pii=pair<int,int>;
using ll = long long;
using ull = unsigned long long;
const ll inf = 1e18;
const int mod = 998244353;
void solve(){
int n;
cin>>n;
vector<int> a(n+1),b(n+1);
for(int i=1;i<=n;i++){
cin>>a[i];
}
for(int j=1;j<=n;j++){
cin>>b[j];
}
if(a[n]!=b[n]){
cout<<"NO\n";
return;
}
for(int i=1;i<n;i++){
if(a[i]==b[i]) continue;
if((a[i]^a[i+1])==b[i]) a[i]=b[i];
}
for(int i=n-1;i>=1;i--){
// cout<<a[i]<<" "<<(a[i]^a[i+1])<<" "<<b[i]<<endl;
if(a[i]==b[i]) continue;
else if((a[i]^a[i+1])==b[i]) a[i]=b[i];
else{
cout<<"NO\n";
return;
}
}
cout<<"YES\n";
}
signed main(){
ios::sync_with_stdio(0);
cin.tie(0);
int ct=1;
cin>>ct;
while(ct--){
solve();
}
return 0;
}
F. Unjust Binary Life
如果让 \(f[x] [y] = 0\),则完全等价于让 \(a[1-x]~到~b[1-y]\) 全部相等
所以 \(ans[x] [y]\) 等于让 \(a[1-x]~到~b[1-y]\) 全部变成 \(1\) 或全部变成 \(0\) 的最小代价
暴力做法是 \(O(n^2)\) 的,考虑如何优化
分别设 \(pa1[x],pa0[x],pb1[y],pb0[x]\), 其中 \(pa1[x]\) 表示 \(a\) 的前 \(x\) 个字符中有几个 \(1\)
对于固定的一个 \(x\),考虑对应的每一个 \(y\)
答案即为 \(min(pa1[x]+pb1[y],~pa0[x]+y-pb1[y])\)
若 \(pa1[x]+pb1[y]~>~pa0[x]+y-pb1[y]\)
则 \(pa1[x]-pa0[x]~>~y-2*pb1[y]\)
此时这一对 \((x,y)\) 对答案的贡献为 \(pa0[x]+y-pb1[y]\), 否则为 \(pa1[x]+pb1[y]\)
固定 \(x\) 后,可以预处理出 \(y-2*pb1[y]\), 排序后二分即可
点击查看代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
using pii=pair<int,int>;
using ll = long long;
using ull = unsigned long long;
const ll inf = 1e18;
const int mod = 998244353;
void solve(){
int n;
cin>>n;
string s,t;
cin>>s>>t;
s=" "+s;
t=" "+t;
vector<int> a(n+1),b(n+1),pa0(n+1),pa1(n+1),pb0(n+1),pb1(n+1);
for(int i=1;i<=n;i++){
if(s[i]=='1') a[i]=1;
if(t[i]=='1') b[i]=1;
pa0[i]=pa0[i-1]+(a[i]==0);
pa1[i]=pa1[i-1]+a[i];
pb1[i]=pb1[i-1]+b[i];
pb0[i]=pb0[i-1]+(b[i]==0);
}
int ans=0;
//当pa0[x]-pa1[x]>2*pb1[y]-y时,用pa1[x]+pb1[y]
//否则用pa0[x]+pb0[y]
vector<pii> d(n+1);
for(int y=1;y<=n;y++){
d[y]={2*pb1[y]-y,y};
}
sort(d.begin()+1,d.end());
vector<int> td(n+1),ppb1(n+1),py(n+1);
for(int i=1;i<=n;i++){
td[i]=d[i].first;
ppb1[i]=ppb1[i-1]+pb1[d[i].second];
py[i]=py[i-1]+d[i].second;
}
int sumpb1=ppb1[n];
int sumy=py[n];
for(int x=1;x<=n;x++){
int pos=upper_bound(td.begin()+1,td.end(),pa0[x]-pa1[x])-td.begin()-1;
ans+=pa1[x]*pos+ppb1[pos];
if(pos<n){
ans+=pa0[x]*(n-pos)+(sumy-py[pos])-(sumpb1-ppb1[pos]);
}
}
cout<<ans<<endl;
}
signed main(){
ios::sync_with_stdio(0);
cin.tie(0);
int ct=1;
cin>>ct;
while(ct--){
solve();
}
return 0;
}
G. Wafu!
设 \(f[i]\) 表示移除 \(1-i\) 所有数需要操作多少次,\(f[i]=f[i-1]*2+1\)
设 \(g[i]\) 表示完全移除 \(1-i\) 后对答案的贡献
则 \(f[val-1]+1\) 即为完全移除掉 \(val\) 需要的次数,\(g[val-1]*val\) 即为对答案的贡献
发现当 \(i>30\) 时,操作次数已经大于 \(k\) 了
每次找到集合中最小的数 \(val\),如果 \(f[val-1]+1<=k\),则可以直接把 \(val\) 完全移除
否则,直接枚举 \(i=~[1~到~min(30, val-1)]\),添加到集合中,每次添加的个数不超过 \(30\) 次
点击查看代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
using pii=pair<int,int>;
using ll = long long;
using ull = unsigned long long;
const ll inf = 1e18;
const int mod = 1e9+7;
using mint = ModInt<mod>;
vector<int> f(50);//对于(1-i)会进行多少次操作
vector<mint> g(50);//删完(1-i)要乘上的数值
int mx=1;//数值最大是多少
void init(){
f[0]=0;
g[0]=1;
while(1){
f[mx]=f[mx-1]*2+1;
g[mx]=g[mx-1]*g[mx-1]*mx;
if(f[mx]>=1e9) break;
mx++;
}
}
void solve(){
int n,k;
cin>>n>>k;
set<int> s;
for(int i=1;i<=n;i++){
int val;
cin>>val;
s.insert(val);
}
mint ans=1;
while(s.size() && k){
int val=*s.begin();
s.erase(s.begin());
if(val<=mx && f[val-1]+1<=k){
k-=f[val-1]+1;
ans*=g[val-1]*val;
}
else{
ans*=val;
k--;
for(int i=1;i<=min(mx,val-1);i++){
s.insert(i);
}
}
}
cout<<ans<<endl;
}
signed main(){
ios::sync_with_stdio(0);
cin.tie(0);
init();
int ct=1;
cin>>ct;
while(ct--){
solve();
}
return 0;
}
自动取模类代码:
点击查看代码
/*支持define int long long 的自动取模类*/
template<const int T>
struct ModInt {
const static int mod = T;
int x;
ModInt(signed x = 0) : x(x % mod) {}
ModInt(long long x) : x(x % mod) {}
int val() { return x; }
ModInt operator + (const ModInt &a) const { int x0 = x + a.x; return ModInt(x0 < mod ? x0 : x0 - mod); }
ModInt operator - (const ModInt &a) const { int x0 = x - a.x; return ModInt(x0 < 0 ? x0 + mod : x0); }
ModInt operator * (const ModInt &a) const { return ModInt(1LL * x * a.x % mod); }
ModInt operator / (const ModInt &a) const { return *this * a.inv(); }
bool operator == (const ModInt &a) const { return x == a.x; };
bool operator != (const ModInt &a) const { return x != a.x; };
void operator += (const ModInt &a) { x += a.x; if (x >= mod) x -= mod; }
void operator -= (const ModInt &a) { x -= a.x; if (x < 0) x += mod; }
void operator *= (const ModInt &a) { x = 1LL * x * a.x % mod; }
void operator /= (const ModInt &a) { *this = *this / a; }
friend ModInt operator + (int y, const ModInt &a){ int x0 = y + a.x; return ModInt(x0 < mod ? x0 : x0 - mod); }
friend ModInt operator - (int y, const ModInt &a){ int x0 = y - a.x; return ModInt(x0 < 0 ? x0 + mod : x0); }
friend ModInt operator * (int y, const ModInt &a){ return ModInt(1LL * y * a.x % mod);}
friend ModInt operator / (int y, const ModInt &a){ return ModInt(y) / a;}
friend ostream &operator<<(ostream &os, const ModInt &a) { return os << a.x;}
friend istream &operator>>(istream &is, ModInt &t){return is >> t.x;}
ModInt pow(int64_t n) const {
ModInt res(1), mul(x);
while(n){
if (n & 1) res *= mul;
mul *= mul;
n >>= 1;
}
return res;
}
ModInt inv() const {
int a = x, b = mod, u = 1, v = 0;
while (b) {
int t = a / b;
a -= t * b; swap(a, b);
u -= t * v; swap(u, v);
}
if (u < 0) u += mod;
return u;
}
};
using mint = ModInt<mod>;

浙公网安备 33010602011771号