Educational Codeforces Round 86 (Div. 2) 題解 (ABCDE)


比賽鏈接:https://codeforces.com/contest/1342

A. Road To Zero

o(*≧▽≦)ツ

#include <bits/stdc++.h>
using namespace std;
#define repeat(i,a,b) for(int i=(a),_=(b);i<_;i++)
#define repeat_back(i,a,b) for(int i=(b)-1,_=(a);i>=_;i--)
int cansel_sync=(ios::sync_with_stdio(0),cin.tie(0),0);
const int N=100010; typedef long long ll;
#define int ll
int T,x,y,a,b;
signed main(){
	cin>>T;
	while(T--){
		cin>>x>>y;
		cin>>a>>b;
		int ans=0;
		if(2*a>b){
			if(x>0 && y>0){
				int t=min(x,y);
				ans+=t*b;
				x-=t;
				y-=t;
			}
			if(x<0 && y<0){
				int t=min(-x,-y);
				ans+=t*b;
				x+=t;
				y+=t;
			}
		}
		ans+=a*(abs(x)+abs(y));
		cout<<ans<<endl;
	}
	return 0;
}

B. Binary Period

(*^▽^*)

#include <bits/stdc++.h>
using namespace std;
#define repeat(i,a,b) for(int i=(a),_=(b);i<_;i++)
#define repeat_back(i,a,b) for(int i=(b)-1,_=(a);i>=_;i--)
int cansel_sync=(ios::sync_with_stdio(0),cin.tie(0),0);
const int N=100010; typedef long long ll;
#define int ll
int T;
string s;
signed main(){
	cin>>T;
	while(T--){
		cin>>s;
		bool a0=1,a1=1;
		repeat(i,0,s.length()){
			if(s[i]=='1')a0=0;
			if(s[i]=='0')a1=0;
		}
		if(a0 || a1)cout<<s;
		else
		repeat(i,0,s.length())
			cout<<"01";
		cout<<endl;
	}
	return 0;
}

C. Yet Another Counting Problem

好了,正片開始

事實上,\((x \bmod a)\) 是有周期性的,周期為 \(a\)\((x \bmod b)\) 的周期為 \(b\),那么 \(g(x)=f(x \bmod a,x \bmod b)\) 呢?顯而易見,\(ab\) 一定是 \(g(x)\) 的其中一個周期

那么我們令 \(g(x)=[x \bmod a \bmod b\not= x \bmod b \bmod a]\),只要維護 \(g(x)\) 的一個周期(長為 \(ab\)),就能很快算出 \(\sum\limits_{i=l}^{r}g(x)\)

(一定有人想問為什么不說人話,要不……直接看代碼吧?逃)

#include <bits/stdc++.h>
using namespace std;
#define repeat(i,a,b) for(int i=(a),_=(b);i<_;i++)
#define repeat_back(i,a,b) for(int i=(b)-1,_=(a);i>=_;i--)
int cansel_sync=(ios::sync_with_stdio(0),cin.tie(0),0);
const int N=100010; typedef long long ll;
#define int ll
int T;
int s[N];
int a,b,q;
int work(int x){
	return x/(a*b)*s[a*b]+s[x%(a*b)];
}
signed main(){
	cin>>T;
	while(T--){
		cin>>a>>b>>q;
		repeat(i,1,a*b+1)
			s[i]=s[i-1]+(i%a%b!=i%b%a); //g(x)的前綴和
		while(q--){
			int x,y; cin>>x>>y;
			cout<<work(y)-work(x-1)<<' ';
		}
		cout<<endl;
	}
	return 0;
}

D. Multiple Testcases

一波巧妙的構造,差點被自己驚艷到/xyx(huge fog)

事實上第一個應該求出的是 \(ans\)。先讓 \(\{m[i]\}\) 升序排列,如果要將大於等於 \(m[i]\) 的所有數存起來,那么一定需要 \(\lceil \dfrac {n-i+1}{c[m[i]]}\rceil\) 個數據點(大於等於 \(m[i]\) 的數有 \(n-i+1\)個),取它們的最大值 \(\max\limits_{i=1}^{n}\lceil \dfrac {n-i+1}{c[m[i]]}\rceil\) 就是 \(ans\)

然后需要構造出怎么存數據點,直接輪流放置即可,即 \(m[1]\) 放第 \(1\) 個, \(m[2]\) 放第 \(2\) 個,……,\(m[ans]\) 放第 \(ans\) 個,\(m[ans+1]\) 放第 \(1\) 個,……,\(m[k\cdot ans+t]\) 放第 \(t\) 個。這個巧妙(霧)的設計可以避免過載,雖然暫時不確定這個方法是不是有鍋/kk

證明?證明是不存在的,不然我現在也不會這么慌

更:楊老師提供了證明(%%%tql)

就 考慮從頭到尾放置 其實是1.2.3...ans然后回到1.2.3...這樣從頭到尾放過來
1.2.3..ans指的是最后的答案
在放置的過程中 如果有超過限制的個數出現 比如8之前只能放3個 總共有5個容器可以放 但是第一個容器放了4個
這時候說明8之前數的個數的肯定超過了3*5+1個 答案就肯定不止5個容器了

#include <bits/stdc++.h>
using namespace std;
#define repeat(i,a,b) for(int i=(a),_=(b);i<_;i++)
#define repeat_back(i,a,b) for(int i=(b)-1,_=(a);i>=_;i--)
int cansel_sync=(ios::sync_with_stdio(0),cin.tie(0),0);
const int N=200010; typedef long long ll;
#define int ll
int a[N],c[N];
int n,k,ans;
signed main(){
	cin>>n>>k;
	repeat(i,1,n+1)cin>>a[i]; sort(a+1,a+n+1);
	repeat(i,1,k+1)cin>>c[i];
	repeat(i,1,n+1)ans=max(ans,(n-i+1+c[a[i]]-1)/c[a[i]]);
	cout<<ans<<endl;
	repeat(i,1,ans+1){
		int cnt=0;
		for(int j=i;j<=n;j+=ans)
			cnt++;
		cout<<cnt<<' ';
		for(int j=i;j<=n;j+=ans)
			cout<<a[j]<<' ';
		cout<<endl;
	}
	return 0;
}

E. Placing Rooks

首先有一個重要的結論,即每一行都一個車/每一列都有一個車,兩者至少滿足其一。如果不滿足,那么我們寫出它的相反命題,即存在一行無車並且存在一列無車,顯然不滿足題意,QED

那么先假設車占據了任一列。經過簡單操作發現,所有車占據的行數恰好等於 \(n-k\),證明略,不相信的可以畫個棋盤搞一下(霧)

然后我用了容斥,先選擇 \(n-k\) 行(\(C_{n}^{n-k}\) 種情況),在列互不相同的情況下每個棋子都無腦放入這 \(n-k\) 行(\((n-k)^n\) 種情況),顯然會多出有空行的情況,所以要減去至少有 \(1\) 個空行(\((n-k-1)^n C_{n-k}^{1}\) 種情況),加上至少有 \(2\) 個空行(\((n-k-2)^n C_{n-k}^{2}\) 種情況),減去至少有 \(3\) 個空行,……公式為 \(C_{n}^{n-k}[(n-k)^n-(n-k-1)^n C_{n-k}^{1}+(n-k-2)^n C_{n-k}^{2}-...]\)(注:“至少有 \(1\) 個空行”“至少有 \(2\) 個空行”等等這些情況是有重復的,所以之后會一加一減來平衡)(很難懂吧,我也覺得,我很久之前就想學容斥專題了,咕到現在)

當然我們剛好考慮一半(注:上面只考慮了車占據任一列的情況,任一行的情況顯然數目相同),所以要乘2。但是但是,\(k=0\) 就不用乘2,特判一下,\(k> n\) 也要特判一下不然 \(n-k\) 是負數了

更:好像是第二類斯特林數qwq,我組合數學還是太菜了

#include <bits/stdc++.h>
using namespace std;
#define repeat(i,a,b) for(int i=(a),_=(b);i<_;i++)
#define repeat_back(i,a,b) for(int i=(b)-1,_=(a);i>=_;i--)
int cansel_sync=(ios::sync_with_stdio(0),cin.tie(0),0);
const int N=200010; typedef long long ll;
const int mod=(0?1000000007:998244353); ll mul(ll a,ll b,ll m=mod){return a*b%m;} ll qpow(ll a,ll b,ll m=mod){ll ans=1; for(;b;a=mul(a,a,m),b>>=1)if(b&1)ans=mul(ans,a,m); return ans;} ll getinv(ll v,ll m=mod){return qpow(v,m-2,m);}
#define int ll
struct CC{
	static const int N=200010;
	ll fac[N],inv[N];
	CC(){
		fac[0]=1;
		repeat(i,1,N)fac[i]=fac[i-1]*i%mod;
		inv[N-1]=qpow(fac[N-1],mod-2,mod);
		repeat_back(i,0,N-1)inv[i]=inv[i+1]*(i+1)%mod;
	}
	ll operator()(ll a,ll b){ //a>=b
		if(a<b)return 0;
		return fac[a]*inv[a-b]%mod*inv[b]%mod;
	}
}C;
int a[N],c[N];
int n,k,ans;
signed main(){
	cin>>n>>k;
	if(k>=n)cout<<0<<endl,exit(0);
	if(k==0)cout<<C.fac[n]<<endl,exit(0);
	repeat(i,0,n-k+1){
		if(i%2==0)ans+=qpow(n-k-i,n)*C(n-k,i)%mod;
		else ans-=qpow(n-k-i,n)*C(n-k,i)%mod;
	}
	ans%=mod;
	(ans*=C(n,n-k))%=mod;
	(ans*=2)%=mod;
	cout<<(ans+mod)%mod<<endl;
	return 0;
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM