A.616问题(签到)
题目
子串是连续的。
果老师最喜爱的字符串是616。
果老师得到了一个纯数字的字符串S,他想知道在可以任意打乱顺序的情况下,最多有多少个不同的子串为616。
当两个子串 S1[l1...r1],S2[l2....r2] 满足 l1不等于l2且r1不等于r2或时它们被认为是不同的。
Input
11
11451419266
Output
1
思路
- 只需要考虑1和6的个数
- 让616最多的格式为6161616.....让前后字符串共用6,6的个数比1的个数多一。
- 设1的个数为cnt1,6的个数为cnt6,则616个数为cnt6-1或者cnt1的个数,取最小值即可,注意没有1或6的情况。
- 公式:max(min(cnt6-1,cnt1),0)
代码
#include<iostream>
#include<bits/stdc++.h>
using namespace std;
int main(){
int cnt1=0, cnt6=0, n;
string ch;
cin >> n >> ch;
for (int i = 0; i < n;i++){
if(ch[i]=='1')
cnt1++;
else if(ch[i]=='6')
cnt6++;
}
cout << max(min(cnt6-1,cnt1),0) << endl;
} B.计数问题(数学)
题目
何老板给果老师出了一个难题:
求有多少个不同的正整数三元组 (i,j,k) 满足 根号i+根号j=根号k ,且i*j<=n。
果老师并不会做,你能略施援手吗?
当两个三元组 (i1,j1,k1),(i2,j2,k2) 满足i1不等于i2或j1不等于j2或k1不等于k2时它们被认为是不同的。
Input
1
Output
1
思路
- 两边平方得到i+j+根号i乘j=k,所以可以知道i乘j为完全平方数
- 我们令i*j=X^2,所以枚举小于N的所有X,在把每个X分解后计数即可
- 注意在x为平方数时只有一种组合,其他情况有两种组合
代码
#include<iostream>
#include<cmath>
using namespace std;
int main(){
long long n,cnt=0;
cin >> n;
for (int i = 1; i * i <= n; i++)
{
for (int j = 1; j <= i;j++){
if(i==j)
cnt++;
else if(i*i%j==0){
cnt+=2;
}
}
}
cout << cnt << endl;
} C.魔法问题(DP)
题目
果老师n个元素( 编号1~n ),第 个元素的能量值为ai。
果老师可以选择至少k个元素来施放一次魔法,魔法消耗的魔力是这些元素能量值的极差。形式化地,若所用元素编号集合为S,则消耗的魔力为选择的集合中的最大值减去最小值的差。
果老师要求每个元素必须被使用恰好一次。
果老师想知道他最少需要多少魔力才能用完所有元素,请你告诉他。
Input
4 2
8 7 114514 114513
Output
2
思路
- 先把能量值排序
- 我们设dp[i]为前i个的最小花费即为前i个的最优情况
- 情况一:dp[i+1]与是前一个dp[i]加上a[i]与a[i-1]的差值即为dp[i+1]=dp[i]+a[i+1]-a[i]
- 情况二:dp[i+1]与前面断开,连接前k个再加上原数组的差即为dp[i+1]=dp[i+1-k]+a[i+1]-a[i-k+2]
- 公式为情况一与情况二取最小值
代码
#include<bits/stdc++.h>
using namespace std;
int main(){
long long n, a[1000005], dp[1000005], k;
cin >> n >> k;
for (long long i = 1; i <= n;i++)
cin >> a[i];
sort(a + 1, a + n + 1);
memset(dp, 0x3f3f3f3f, sizeof(dp));
dp[k] = a[k] - a[1];
for (long long i = k + 1; i <= n; i++)
{
dp[i] = min(dp[i - 1] + (a[i] - a[i - 1]), dp[i - k] + (a[i] - a[i - k + 1]));
}
cout << dp[n] << endl;
} D.通道问题(DP)
题目
果老师n个元素( 编号1~n ),第 个元素的能量值为ai。
果老师可以选择至少k个元素来施放一次魔法,魔法消耗的魔力是这些元素能量值的极差。形式化地,若所用元素编号集合为S,则消耗的魔力为选择的集合中的最大值减去最小值的差。
果老师要求每个元素必须被使用恰好一次。
果老师想知道他最少需要多少魔力才能用完所有元素,请你告诉他。
Input
2
1 2
Output
1
思路
- 首先将权值去重(权值相等的点连接代价为0),
- 设去重之后有𝑚个点,接下来找到最小的二进制位k,满足存在vi的这个二进制位是0且存在vj的这个二进制位是1,答案为2^k*𝑚 − 1
- 相当于所有的这位是0的点跟𝑗连边,是1的点跟𝑖连边。
代码(出题人)
#include <bits/stdc++.h>
using namespace std;
const int N = 2e5 + 5;
int n, k;
int v[N], va, vo, ans;
int main(){
cin >> n;
for (int i = 1; i <= n; i++)
cin >> v[i];
sort(v + 1, v + n + 1);
va = 0x7fffffff;
for (int i = 1; i <= n; i++)
{
va &= v[i];
vo |= v[i];
}
v[n + 1] = 2e9;
for (int i = n; i; i--)
k += (v[i] != v[i + 1]);
va ^= vo;
for (int i = 0; i <= 30; i++)
{
int cur = 1 << i;
if(va&cur) {
ans = cur * (k - 1);
break;
}
}
cout << ans << endl;
return 0;
} 一些其他的东西
如有错误请指出!

京公网安备 11010502036488号