T1 隔离
T384651 隔离 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 内部题
题目大意
给出一个数组,将一个数按照数组顺序不断增加,加一次需要另外增加400,若一次累计增加超过240,则要另外加10080,求累加后数字最小为几
思路
贪心思路,首先尽可能少加,如果超过240了则要计算一直加到最后来的便宜还是悬崖勒马来的便宜。
代码
#include <bits/stdc++.h>
#define endl '\n'
using namespace std;
const int N = 1005;
int n, flag, ans, sum[N];
int mian(){
cin >> n;
for(int i=1; i<=n; i++){
cin >> sum[i];
if (sum[i] > 240) flag = 1;
sum[i] += sum[i - 1];
}
if(flag == 0){
int l = 0;
for(int i = 1; i < n; i++){
if(sum[i]-sum[l] >= 240){
l = i-1;
ans += 400;
}
}
ans = min(ans, 10080);
}
else ans = 10080;
ans += sum[n] + 400;
cout << ans << endl;
}
//故意少写了两个符号
T2 循环移位
T384652 循环移位 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 内部题
题目大意
有一个可以不断往左边移的数组,求最大的回文串。
思路
首先写出来一个非常简单的判断最大回文串的代码,这点不加赘述,是个人都会。接下来有两种做法,一种是不断往左边移,遍历所有可能,复杂度O(n),期望得分40pt,实际应该会高一点。
第二种是我的做法,首先复制一个字符串,例如输入aab,则复制一下变成aabaab,这个时候对这个大的字符串求最大回文串,答案是5,显然不是正确答案(3),怎么办呢?注意这个最大的回文串aabaa,我们对于这个串可以发现中间的aba明显符合要求,若这个的长度的奇偶性与n的奇偶性相同,则答案就是n,否则答案为n-1。期望ac,实际ac。
代码
#include<bits/stdc++.h>
#define endl '\n'
using namespace std;
int cnt(const string &s){
int n = s.size();
if(n == 0) return 0;
int code;
int by;
int waterpail;
vector<vector<bool>> dp(n, vector<bool>(n, false));
int c = 1;
for(int i=0; i<n; i++){
dp[i][i] = true;
}
int EAS,on,top;
for(int i=0; i<n-1; i++){
if(s[i] == s[i + 1]){
dp[i][i + 1] = true;
c = 2;
}
}
for(int len=3; len<=n; len++){
for(int i=0; i<=n-len; i++){
int j = i + len - 1;
if(s[i] == s[j] && dp[i + 1][j - 1]){
dp[i][j] = true;
if(len>c){
c = len;
}
}
}
}
return c;
}
int main(){
int n;
cin >> n;
string s;
cin >> s;
string ss = s+s;
int ans = cnt(ss);
if(ans > n){
if((ans+n)&2){
cout << n-1 << endl;
}
else{
cout << n << endl;
}
}
else{
cout << ans << endl;
}
}
T3
T384653 武器获取 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 内部题
题目大意
难以概括,见题。
思路
我的做法比较诡异,不说了,0pt
题解强,我看题解,对于每一个区间都进行一次计数,统计每种武器的出现次数,如果出现次数达标,则收获这个武器。输出答案时进行组合数的判定即可。时间n方,期望40pt。
100pt题解难以理解,是通过优化计数进行剪枝吗?
代码
40pt
while(m--){
cin >> l >> r >> k;
s = 0, ans = 0;
for(int i = 0; i <= 100005; i++)
b[i] = 0;
for(int i = l; i <= r; i++)
if(a[i] <= 100005){
b[a[i]]++;
if(b[a[i]] == a[i]){
s++;
}
}
if(s >= k){
ans = 1;
for(int i = 0; i < k; i++){
ans *= s - i;
}
for(int i = 1; i <= k; i++){
ans /= i;
}
}
cout << ans << endl;
}
100pt
long long C(int n,int m) {
if (n < m) return 0;
if (m == 1) return n;
else if (m == 2) return n * (n - 1) / 2;
else if (m == 3) return 1ll * n * (n - 1) * (n - 2) / 6;
else return 1ll * n * (n - 1) * (n - 2) * (n - 3) / 24;
}
cin >> m;
while (m--) {
cin >> l >> r >> k;
int ans = 0;
for (int i = 1; i <= tot; i++) { // 枚举每一种武器
if (pre[i][r] - pre[i][l - 1] >= b[i]) ans++; // 出现次数符合要求,则 ans++ 更新武器数量
}
cout << C(ans, k) << endl;
}
for (int i = 1; i <= n; i++) { // 读入部分,统计每种武器的出现次数
cin >> a[i];
if (a[i] <= n) cnt[a[i]]++; // 注意这个 if,谨防 RE
}
for (int i = 1; i <= n; i++) {
if (cnt[i] >= i) { // 这个 if 只会进入根号 n 次
b[++tot] = i; // 记录这种武器需要的次数
for (int j = 1; j <= n; j++) // 统计前缀和
pre[tot][j] += pre[tot][j - 1] + (a[j] == i);
}
}
我没有拼接,但是看得懂
T4
T384655 最大公约数的期望 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
题目大意
考察期望,见原题
思路
骗分之神能骗到20pt,部分分之神能用快速幂拿到40pt,而题解之神就不同,用我看不懂的方法拿到了100pt。
代码
20pt
#include<bits/stdc++.h>
#define endl '\n'
using namespace std;
int main(){
int n;
cin >> n;
vector<int> a(n+1);
for(int i=1; i<=n; i++){
cin >> a[i];
}
cout << __gcd(a[0],a[1]) << endl;
}
我防伪都不想做,要是这都写不出来这辈子有了
40pt
cin >> n;
numk = (n * (n - 1) / 2) % mod; // 算出 C(n,2)
inv = q_pow(numk, mod - 2); // 用快速幂算出逆元,这个是期望的分母
for (int i = 1; i <= n; i++) cin >> a[i];
for (int i = 1; i <= n; i++) for (int j = i + 1; j <= n; j++) ans += __gcd(a[i], a[j]); // 两重循环计算所有 gcd 之和,也就是期望的分母
cout << ans * inv % mod; // 分子乘以分母的逆元就是答案
我这辈子有了,这么简单的我做不出来 LLLL
100pt
不放代码了,看不懂就尊重代码