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 o i)和(i + 1 o 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: