多校A层冲刺NOIP2024模拟赛18
赛时电脑死了,恼了就没交。赛后交是155pts。
T1 是二分答案+三维前缀和check,T2 瞎写了个搜索。
T1 选彩笔(rgb)
将r,g,b看做三个维度。
答案显然有可二分性,直接二分答案。那么就转化为是否存在一个边长为\(mid\)三维正方体,其内部有大于\(k\)个点。
三维前缀和维护即刻,时间复杂度是\(O(V^3\log V)\)的。
但貌似三维偏序也能做,只是非常非常麻烦?(雾)
点此查看代码
#include <bits/stdc++.h>
using namespace std ;
#define rep(i,s,t,p) for(int i = s;i <= t;i += p)
#define drep(i,s,t,p) for(int i = s;i >= t;i -= p)
#ifdef LOCAL
FILE *InFile = freopen("in.in","r",stdin),*OutFile = freopen("out.out","w",stdout);
// FILE *ErrFile = freopen("err.err","w",stderr);
#else
FILE *InFile = freopen("rgb.in","r",stdin),*OutFile = freopen("rgb.out","w",stdout);
#endif
using ll = long long;using ull = unsigned long long;
using db = double;using ldb = long double;
const int N = 1e5 + 100,V = 257;
struct Node {int r,g,b;}a[N];
int n,K,maxn[3],sum[V][V][V],VA = 256;
inline int P(int x){return x < 0? 0:x;}
inline int val(int i , int j , int k , int mid){
return sum[i][j][k]-sum[P(i-mid-1)][j][k]-
sum[i][P(j-mid-1)][k]-sum[i][j][P(k-mid-1)]+
sum[P(i-mid-1)][P(j-mid-1)][k]+sum[P(i-mid-1)][j][P(k-mid-1)]+
sum[i][P(j-mid-1)][P(k-mid-1)]-sum[P(i-mid-1)][P(j-mid-1)][P(k-mid-1)];
}
inline bool check(int mid) {
rep(i,1,VA,1) rep(j,1,VA,1) rep(k,1,VA,1)
if (val(i,j,k,mid) >= K) return true;
return false ;
}
inline void solve(){
cin>>n>>K;
rep(i,1,n,1){
cin>>a[i].r>>a[i].g>>a[i].b;
a[i].r++,a[i].b++,a[i].g++;
maxn[0] = max(maxn[0],a[i].r),maxn[1] = max(maxn[1],a[i].g),maxn[2] = max(maxn[2],a[i].b);
sum[a[i].r][a[i].g][a[i].b]++;
}
rep(i,1,VA,1) rep(j,1,VA,1) rep(k,1,VA,1)
sum[i][j][k] += (sum[i-1][j][k]+sum[i][j-1][k]+sum[i][j][k-1]-sum[i][j-1][k-1]-sum[i-1][j][k-1]-sum[i-1][j-1][k]+sum[i-1][j-1][k-1]);
int l = 1,r = 256,ans = 0;
while(l <= r){
int mid = (l + r) >> 1;
if (check(mid)) ans = mid,r = mid - 1;
else l = mid + 1 ;
}
cout<<ans<<'\n';
}
signed main() {
cin.tie(nullptr)->sync_with_stdio(false);
solve();
}
T2 兵蚁排序(sort)
考虑排序的性质是减少序列中的逆序对,且不会新增逆序对。
然后如果\(A\)中有的逆序对而\(B\)中没有,那么就将这俩swap一下,冒泡即可,时间复杂度\(O(n^2)\)。
点此查看代码
#include<bits/stdc++.h>
using namespace std;
#define rep(i,s,t,p) for(int i = s;i <= t;i += p)
#define drep(i,s,t,p) for(int i = s;i >= t;i -= p)
#ifdef LOCAL
FILE *InFile = freopen("in.in","r",stdin),*OutFile = freopen("out.out","w",stdout);
// FILE *ErrFile = freopen("err.err","w",stderr);
#else
FILE *InFile = freopen("sort.in","r",stdin),*OutFile = freopen("sort.out","w",stdout);
#endif
using ll = long long;using ull = unsigned long long;
using db = double;using ldb = long double;
const int N = 1e3 + 10;
int n,a[N],b[N];
#define pii pair<int,int>
#define mk make_pair
vector<pii> ans;
int cta[N],ctb[N];
inline void solve(){
cin>>n;vector<pii>().swap(ans);
rep(i,1,n,1) cta[i] = ctb[i] = 0;
rep(i,1,n,1) cin>>a[i];rep(i,1,n,1) cin>>b[i];
bool flag = true;
rep(i,1,n,1){
if(!flag) break;
ctb[b[i]]++;
int j = 1,k = 0;
while(j <= n){
if(a[j] == b[i]) k++;
if(k == ctb[b[i]]) break;
j++;
}
drep(k,j-1,max(ctb[b[i]],i),1){
if(a[k] > a[k + 1]){
ans.push_back(mk(k,k+1));
swap(a[k],a[k+1]);
}
else{
flag = false;break;
}
}
}
if(!flag) cout<<"-1\n";
else{
cout<<"0\n"<<ans.size()<<'\n';
for(auto i:ans) cout<<i.first<<' '<<i.second<<'\n';
}
}
signed main(){
cin.tie(nullptr)->sync_with_stdio(false);
int T;cin>>T;while(T--) solve();
}
T3 人口局 DBA(dba)
容斥。
设\(f_{i,j}\)表示已经当前已经填了\(i-1\)个数,和为\(j\)的方案数。
有容斥柿子为\(f_{i,j}=\sum\limits_{k=0}^i(-1)^k\mathrm{C}_i^k\mathrm{C}_{j+i-km-1}^{i-1}\)。
答案为\(\sum\limits_{i=1}^n\sum\limits_{j=0}^{a_i-1}f_{n-i,s_i-j}\),其中\(s_i\)表示\(a\)的后缀和。
将这个柿子拆开,有
转化一下就是
发现后面的\(s_i-km,n-i-1\)是个常量,所以后面的柿子等价于求
将这玩意扔到杨辉三角上,然后画一下图,推一下,可以得到后边这个柿子就是\(\mathrm{C}_{n+m+1}^{m+1}-\mathrm{C}_{n+m-p}^{m+1}\)
然后后面的就可以\(O(1)\)求了,直接递推就行,时间复杂度\(O(n^2)\)
点此查看代码
#include<bits/stdc++.h>
using namespace std;
#define rep(i,s,t,p) for(int i = s;i <= t;i += p)
#define drep(i,s,t,p) for(int i = s;i >= t;i -= p)
#ifdef LOCAL
FILE *InFile = freopen("in.in","r",stdin),*OutFile = freopen("out.out","w",stdout);
#else
FILE *InFile = freopen("dba.in","r",stdin),*OutFile = freopen("dba.out","w",stdout);
#endif
using ll = long long;using ull = unsigned long long;
using db = double;using ldb = long double;
const int N = 2e3 + 10,mod = 1e9 + 7;
inline int power(int a,int b,int mod){
int res = 1;
for(;b;b >>= 1,a = 1ll*a*a%mod)
if(b&1) res = 1ll*res*a%mod;
return res;
}
inline int Inv(int a){return power(a,mod-2,mod);}
int fac[N*N],inv[N*N],m,n,a[N],sum[N];
inline int C(int n,int m){return m>n?0:1ll*fac[n]*inv[n-m]%mod*inv[m]%mod;}
inline void solve(){
cin>>m>>n;rep(i,1,n,1) cin>>a[i],a[i] += a[i - 1];
fac[0] = 1;rep(i,1,m*n,1) fac[i] = 1ll*fac[i-1]*i%mod;
inv[m*n] = Inv(fac[m*n]);
drep(i,m*n-1,0,1) inv[i] = 1ll*inv[i+1]*(i+1)%mod;
ll ans = 0;
rep(i,1,n,1){
int S = a[n] - a[i - 1] ;
rep(j,0,n-i,1){
int sgn = j&1?-1:1;
ans = ((((1ll*sgn*C(n-i,j)*((1ll*C(S-j*m+n-i,n-i)-C(S-a[i]+a[i-1]-j*m+n-i,n-i)+mod)%mod))%mod)+mod)%mod+ans)%mod;
}
}
cout<<ans;
}
signed main(){
cin.tie(nullptr)->sync_with_stdio(false);
solve();
}
T4
不会
有人说座位是按模拟赛调的,那我以后赛时都不交,看看他能给我排到哪里。
本文来自博客园,作者:CuFeO4,转载请注明原文链接:https://www.cnblogs.com/hzoi-Cu/p/18528626