2021“MINIEYE杯”中國大學生算法設計超級聯賽(5)
1003.VC Is All You Need
- 題意
給你一個k維平面,問你是不是隨意放n個點都能用k-1條線分隔開
- 思路
emmmm, 思考一下, n > k + 1都是不行的。。
code:
void solve(){
ll n,k;
cin >> n >> k;
if(n > k+1){
cout << "No" << endl;
}else cout << "Yes" << endl;
}
1004.Another String
- 題意
給定n,k和字符串s, 讓你求出從\(1 \to i\)和\(i + 1 \to n\)中任意挑選兩個子字符串,要求長度相同,並且着一堆字符串中最多有k個字符不同,問你有多少對這樣的子字符串
- 思路
暴力+雙指針,求出f[i][j]表示i,j位置為兩字符串的左端點,滿足要求的最大長度,然后雙指針枚舉長度。
在紙上模擬一邊在通過一些推導可以發現每個位置的貢獻是固定的,用差分+兩次前綴和便可計算答案。。
code:
int f[N][N];
char str[N];
int ans[N];
void solve(){
int n,k;
cin >> n >> k;
cin >> (str + 1);
// 枚舉右端點
for(int st = 2;st <= n;st ++) {
int len = 0;
int dif = 0;
// 固定左右端點長度,往后雙指針枚舉
for(int i = 1, j = st;j <= n;j ++,i ++) {
while(dif <= k) {
dif += str[i + len] != str[j + len];
len ++;
}
f[i][j] = min(len - 1, min(j - i, n - j + 1));
len --;dif -= (str[i] != str[j]);
}
}
memset(ans,0,sizeof ans);
for(int i = 1;i <= n;i ++) {
for(int j = i + 1;j <= n;j ++) {
ans[i] ++;
ans[i + f[i][j]] --;
ans[j] -= f[i][j];
ans[j + 1] += f[i][j];
}
}
for(int i = 1;i <= n;i ++) ans[i] += ans[i - 1];
for(int i = 1;i <= n;i ++) {
ans[i] += ans[i - 1];
if(i != n) cout << ans[i] << endl;
}
}
1006.Cute Tree
- 題意
給出一個類三叉樹的構造方法,讓你輸出它能建立的節點個數
- 思路
按着圖上的代碼打就行了,又不會超時
code:
int a[N];
int tot;
void build(int id,int l,int r) {
tot ++;
id = tot;
if(l == r) {
return;
}
if(r - l + 1 == 1) {
int mid = l + r >> 1;
tot += 2;
return;
}else {
int B = l + ceil((r - l + 1) / 3.0) - 1;
int C = B + r >> 1;
if(B >= l)
build(id,l,B);
if(C >= B + 1)
build(id,B + 1,C);
if(r >= C+1);
build(id,C+1,r);
}
}
void solve(){
tot = 0;
int n;
cin >> n;
for(int i = 1;i <= n;i ++) cin >> a[i];
build(1,1,n);
cout << tot << endl;
}
1007.Banzhuan
- 題意
給一個\(n * n * n\)的立方體空間, 你只能用1立方體積的小立方塊去填,小立方體放在一個位置,那么它的價值就是\(x * y^2 * z\), 並且,如果你防止的地方的底部(z軸)為空,那么它會一直往下掉。
- 思路
然后, dddd , 套公式了。。
code:
const ll mod = 1e9 + 7;
ll qpow(ll a, ll b, ll mod){
ll ans = 1;
while(b){
if(b & 1)ans=ans*a%mod;
b>>=1;
a=a*a%mod;
}
return ans;
}
void solve(){
ll n;
cin >> n;
n %= mod;
ll res = (n%mod*(n+1)%mod*qpow(2,mod-2,mod)%mod)%mod;
// cnt計算側面的立方體
ll cnt = (res%mod*(n%mod*(n+1)%mod*(2*n+1)%mod*qpow(6,mod-2,mod)%mod-1+mod)%mod)%mod;
// cnt1計算正面
ll cnt1 = (res%mod-1+mod)%mod*(res%mod)%mod;
// cnt2底面
ll cnt2 = ((res%mod)%mod*(n%mod*(n+1)%mod*(2*n+1)%mod)%mod*qpow(6,mod-2,mod)%mod)%mod;
ll ans = (cnt+cnt1+cnt2 - (res-1+mod)%mod - ((n%mod*(n+1)%mod*(2*n+1)%mod*qpow(6,mod-2,mod)%mod-1+mod)+1ll*2*mod)%mod+ 1ll*5*mod)%mod;//最小值
ll ans1 = (n%mod*n%mod*cnt2%mod)%mod; // 最大值
cout << ans << endl;
cout << ans1 << endl;
}
1009.Array
- 題意
給出一個長度為n的序列,滿足一對(l,r)及(\(a_l,a_{l+1}···,a_r\))之中,眾數出現的次數嚴格大於其他非眾數出現的次數
- 思路
寫了半天的線段樹瘋狂t,給出的數據倒是能過,我人已傻,占坑
code: