Educational Codeforces Round 113 (Rated for Div. 2)
文章目录
A. Balanced Substring
解释
知道到一个 ba 或者 一个 ab就行了
代码
int tt; cin>>tt;
while(tt --) {
int n; cin>>n;
string s; cin>>s;
if(n == 1) {
cout<<"-1 -1"<<endl;
continue;
}
bool plas = false;
for(int i=1;i<n;i++) {
if((s[i] == 'a' && s[i-1] == 'b') || (s[i] == 'b' && s[i-1] == 'a')) {
plas = true;
cout<<i<<" "<<i+1<<endl;
break;
}
}
if(!plas) cout<<"-1 -1"<<endl;
}
B. Chess Tournament
解释
模拟,先填等于符号,剩下的,如果没有+则找一个空位填+,其它填减。
也可以把剩下k为1的人,按第i人赢第i+1人,第n人赢第1人这样来构造。
代码
int tt; cin>>tt;
while(tt --) {
int n; cin>>n;
string s; cin>>s;
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
ans[i][j] = '1';
for(int i=1;i<=n;i++) {
if(s[i-1] == '1') {
for(int j=1;j<=n;j++) {
if(i == j) ans[i][j] = 'X';
else ans[i][j] = ans[j][i] = '=';
}
}
}
bool ok = true;
for(int i=1;i<=n;i++) {
bool plas = false;
if(s[i-1] == '2') {
for(int j=1;j<=n;j++) {
if(i == j) ans[i][j] = 'X';
else if(ans[i][j] == '1') {
if(!plas) ans[i][j] = '+',ans[j][i] = '-',plas = true;
else ans[i][j] = '-',ans[j][i] = '+';
}else if(ans[i][j] == '+') plas = true;
}
if(!plas) ok = false;
}
}
if(!ok) cout<<"NO"<<endl;
else {
cout<<"YES"<<endl;
for(int i=1;i<=n;i++,cout<<endl)
for(int j=1;j<=n;j++)
cout<<ans[i][j];
}
}
C. Jury Meeting
解释
记录最大值和次大值
- 如果相差大于1,则答案为0。
- 相差为0,则为n的全排列
- 相差为1,则可以知道,最大值在所有次大值后面,则是不合法的。然而考虑合法状态却不好计算
假设次大值的个数为 c n t cnt cnt ,那么可以枚举最大值的位置 (i + 1)。 最大值只有一个
每次得到的不合法结果为
C
i
c
n
t
×
(
c
n
t
)
!
×
(
n
−
c
n
t
−
1
)
!
.
C_{i}^{cnt} \times(cnt)! \times (n - cnt - 1)!.
Cicnt×(cnt)!×(n−cnt−1)!.
代码
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#include<bits/stdc++.h>
using namespace std;
const int N = 2e5 + 10;
const int mod = 998244353;
#define int long long
typedef long long ll;
int a[N],fact[N],infact[N];
int qmi(int a,int b) {
int res = 1;
while(b) {
if(b & 1) res = res * a % mod;
a = a *a % mod;
b >>= 1;
}
return res;
}
void init(int n){
fact[0] = infact[n] = 1;
for(int i=1;i<=n;i++) fact[i] = fact[i-1] * i % mod;
infact[n] = qmi(fact[n],mod-2);
for(int i=n-1;i>=0;i--) infact[i] = infact[i+1] * (i+1) % mod;
}
int C(int n,int m){
return fact[n] * infact[m] % mod * infact[n-m] % mod;
}
signed main(){
IOS
init(N-1);
int tt; cin>>tt;
while(tt --) {
int n; cin>>n;
int ma1 = -1,ma2 = -1;
for(int i=1;i<=n;i++) cin>>a[i];
for(int i=1;i<=n;i++) {
if(a[i] >= ma1) ma2 = ma1,ma1 = a[i];
else if(a[i] > ma2) ma2 = a[i];
}
if(ma1 - ma2 > 1) cout<<0<<endl;
else if(ma1 == ma2) cout<<fact[n]<<endl;
else {
int cnt = 0;
for(int i=1;i<=n;i++) if(a[i] == ma2) cnt ++;
int ans = fact[n],k = fact[n-cnt-1],kk = fact[cnt];
for(int i=n-1;i>=cnt;i--)
ans = (ans - C(i,cnt) * kk % mod * k % mod + mod) % mod;
cout<<ans<<endl;
}
}
return 0;
}
D. Inconvenient Pairs
解释
定义两行线之间的为 “行”,两列线之间的为 “列”。
对于相同 “行” 和相同 “列” 的才会有贡献。
可以对于每一行,push到vector里面,相同列的个数计数(用二分寻找对应的列)。 这一行的贡献为 ∏ c n t i \prod cnt_i ∏cnti
列同理。
代码
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#include<bits/stdc++.h>
using namespace std;
const int N = 1e6 + 10;
const int mod = 998244353;
//#define int long long
typedef long long ll;
#define endl "\n"
int cnt[N];
vector<int> Y[N],X[N];
ll cal(vector<int> &T) {
ll res = 0;
int sum = (int)T.size();
if(sum == 0) return res;
map<int,int> mp;
for(auto j : T) mp[j] ++;
for(auto j : mp) {
ll k = j.second;
sum -= k;
res += k * sum;
}
return res;
}
signed main(){
IOS
int tt; cin>>tt;
while(tt --) {
int n,m,k; cin>>n>>m>>k;
vector<int> x,y;
for(int i=1,a;i<=n;i++) cin>>a,x.push_back(a);
for(int i=1,a;i<=m;i++) cin>>a,y.push_back(a);
for(int i=0;i<=m;i++) X[i].clear();
for(int i=0;i<=n;i++) Y[i].clear();
for(int i=1;i<=k;i++) {
int a,b; cin>>a>>b;
int pos1 = upper_bound(x.begin(),x.end(),a) - x.begin() - 1;
int pos2 = upper_bound(y.begin(),y.end(),b) - y.begin() - 1;
if(x[pos1] == a && y[pos2] == b) continue;
if(x[pos1] == a) X[pos2].push_back(pos1);
else Y[pos1].push_back(pos2);
}
ll ans = 0;
for(int i=0;i<=m;i++) ans += cal(X[i]);
for(int i=0;i<=n;i++) ans += cal(Y[i]);
cout<<ans<<endl;
}
return 0;
}