今天看不下去数电vp一场div2,搞A搞了很长时间,导致后面没有时间写,不过今天补题的时候全是独立补出来的没有看题解
vp3题,补3题
A - Kids Seating
最开始想的是与质数有关,乱七八糟搞了半天,结果最后回头一想直接按照此代码输出即可。
首先我们至少找一个所有数都有的因子,我想到了2,然后又想某数不能全是另一个数的因子,于是发现对于n来说,选择n+1→2×nn+1\to 2×nn+1→2×n这n个数一定满足上述条件,然后就A了
#define IO ios::sync_with_stdio(false);cin.tie();cout.tie(0)
#pragma GCC optimize(2)
#include<set>
#include<map>
#include<cmath>
#include<stack>
#include<queue>
#include<random>
#include<bitset>
#include<string>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<unordered_map>
#include<unordered_set>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int N=200010;
int main()
{IO;int T=1;cin>>T;while(T--){int n;cin>>n;for(int i=2*n;i>n;i--)cout<<2*i<<' ';cout<<'\n';}return 0;
}
B - Saving the City
首先把连续的地雷搞出来,每一个连续的地雷可以随着前面连续的地雷一起引爆,花费连接的代价,或者自己引爆,花费引爆的代价,两者相比取最小即可。
#define IO ios::sync_with_stdio(false);cin.tie();cout.tie(0)
#pragma GCC optimize(2)
#include<set>
#include<map>
#include<cmath>
#include<stack>
#include<queue>
#include<random>
#include<bitset>
#include<string>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<unordered_map>
#include<unordered_set>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int N=200010;
int f[N];
int main()
{IO;int T=1;cin>>T;while(T--){int a,b;cin>>a>>b;string s;cin>>s;int n=s.size();vector<pair<int,int>> seg;s="0"+s;seg.push_back({0,n+1});for(int i=1;i<=n;i++){if(s[i]=='0') continue;int j=i;while(j<=n&&s[j]=='1') j++;seg.push_back({i,j-1});i=j;}f[1]=a;for(int i=2;i<seg.size();i++){int cnt=seg[i].first-seg[i-1].second-1;f[i]=f[i-1]+min(b*cnt,a);}cout<<f[seg.size()-1]<<'\n';}return 0;
}
C - The Delivery Dilemma
二分答案即可
#define IO ios::sync_with_stdio(false);cin.tie();cout.tie(0)
#pragma GCC optimize(2)
#include<set>
#include<map>
#include<cmath>
#include<stack>
#include<queue>
#include<random>
#include<bitset>
#include<string>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<unordered_map>
#include<unordered_set>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int N=200010;
int n;
int a[N],b[N];
bool check(int x)
{ll now=0;for(int i=1;i<=n;i++)if(a[i]>x) now+=b[i];return now<=x;
}
int main()
{IO;int T=1;cin>>T;while(T--){ cin>>n;for(int i=1;i<=n;i++) cin>>a[i];for(int i=1;i<=n;i++) cin>>b[i];int l=0,r=1e9+1;while(l<r){int mid=l+r>>1;if(check(mid)) r=mid;else l=mid+1;}cout<<l<<'\n';}return 0;
}
D - Extreme Subtraction
看着像差分那么就是差分!
构造差分数组,然后将原数组1→k1\to k1→k减一,等价于差分数组d1−1d_1-1d1−1和dk+1+1d_{k+1}+1dk+1+1,将后面k个数减一等价于差分数组某位置-1,如果原数组满足题意只需让差分数组全是0,然后随意搞搞就行了太晚了懒得写了
注意差分数组的构造过程
#define IO ios::sync_with_stdio(false);cin.tie();cout.tie(0)
#pragma GCC optimize(2)
#include<set>
#include<map>
#include<cmath>
#include<stack>
#include<queue>
#include<random>
#include<bitset>
#include<string>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<unordered_map>
#include<unordered_set>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int N=300010;
const ll mod=1e9+7;
int a[N],d[N];
int main()
{IO;int T=1;cin>>T;while(T--){int n;cin>>n;for(int i=1;i<=n;i++) cin>>a[i];for(int i=1;i<=n;i++) d[i]=a[i]-a[i-1];ll cnt=0;for(int i=2;i<=n;i++)if(d[i]<0) cnt-=d[i];if(cnt>d[1]) cout<<"NO\n";else cout<<"YES\n";}return 0;
}
E - Long Permutation
这题能够想到非常高兴
13!=622702080013!=622702080013!=6227020800
14!=8717829120014!=8717829120014!=87178291200
观察我们不难发现我们最多会只需2×105×1052×10^5×10^52×105×105次next_permutation
操作,分析不难知道如果n很大,进行操作2也只会改变后面14个数,其他前面的数位置不会改变,于是可以每次暴力让最后14个数进行next_permutation
操作,知道排名求排列数有一个著名的算法——逆康托展开,然后分块计算即可。
前几天逛知乎的时候无意间学了一下康托展开,这就用上了很高兴。
#define IO ios::sync_with_stdio(false);cin.tie();cout.tie(0)
#pragma GCC optimize(2)
#include<set>
#include<map>
#include<cmath>
#include<stack>
#include<queue>
#include<random>
#include<bitset>
#include<string>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<unordered_map>
#include<unordered_set>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int N=200010;
const ll mod=998244353;
ll fact[20];
int P[20],A[20];
ll a[N],s[N];
void calc(int n,ll x)
{vector<int> rest(n,0);iota(rest.begin(), rest.end(), 1);memset(P,0,sizeof P);memset(A,0,sizeof A);for (int i = 1; i <= n; ++i){A[i]=x/fact[n-i];x%=fact[n-i];}for (int i = 1; i <= n; ++i){P[i]=rest[A[i]];rest.erase(lower_bound(rest.begin(), rest.end(), P[i]));}
}
int main()
{IO;int T=1;//cin>>T;while(T--){int n,q;cin>>n>>q;fact[0]=1;for(int i=1;i<=14;i++) fact[i]=i*fact[i-1];for(int i=1;i<=n;i++) a[i]=i,s[i]=s[i-1]+a[i];ll now=0;if(n<=14){while(q--){int op;cin>>op;if(op==1){int l,r;cin>>l>>r;ll res=0;calc(n,now);for(int i=l;i<=r;i++) res+=P[i];cout<<res<<'\n';}else{int x;cin>>x;now+=x;}}}else{while(q--){int op;cin>>op;if(op==1){int l,r;cin>>l>>r;ll res=0;calc(14,now);int bd=n-14;if(r<=bd) res+=s[r]-s[l-1];else if(l>bd){for(int i=l;i<=r;i++) res+=P[i-bd]+bd;}else{res+=s[bd]-s[l-1];for(int i=bd+1;i<=r;i++) res+=P[i-bd]+bd;}cout<<res<<'\n';}else{int x;cin>>x;now+=x;}}}}return 0;
}
F - Identify the Operations
猜结论,考虑当前数的两端的数,如果某数不存在b数组中或者在b数组中的位置小于目前的数贡献+1,每次乘积计算贡献即可。
#define IO ios::sync_with_stdio(false);cin.tie();cout.tie(0)
#pragma GCC optimize(2)
#include<set>
#include<map>
#include<cmath>
#include<stack>
#include<queue>
#include<random>
#include<bitset>
#include<string>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<unordered_map>
#include<unordered_set>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int N=200010;
const ll mod=998244353;
int n,k;
int a[N],b[N];
int pos[N];
int st[N];
int main()
{IO;int T=1;cin>>T;while(T--){cin>>n>>k;for(int i=1;i<=n;i++) pos[i]=st[i]=0;for(int i=1;i<=n;i++) {cin>>a[i];pos[a[i]]=i;}for(int i=1;i<=k;i++) {cin>>b[i];st[b[i]]=i;}ll res=1;for(int i=1;i<=k;i++){int p=pos[b[i]];int now=0;if(p>1&&st[a[p-1]]<i) now++;if(p<n&&st[a[p+1]]<i) now++;res=res*now%mod;}cout<<res<<'\n';}return 0;
}