2024 暑假友谊赛-热身2
2024.7.12 14:00————17:00
过题数4/8
补题数5/8
- CodeForces - 1265E
- CodeForces 911F
- CodeForces 1870E
- AtCoder tenka1_2017_c
- AtCoder diverta2019_b
- AtCoder diverta2019_c
- AtCoder diverta2019_d
- AtCoder abl_d
A - Beautiful Mirrors
题解:
n面镜子,每一面都有p/100的概率回答漂亮,回答不漂亮就得从头再来,一直到最后一面镜子为漂亮时就停止,求多少天可以到最后一面镜子的期望。
快速幂加费马小定理,逆模不太会求,直接copy的代码。由于每次k天之后得再过一天到新的一天进行,所以得加一。
代码:
#include<iostream>
#include<algorithm>
using namespace std;
#define int long long
#define double long double
int p[200005];
int mt[200005];
const int MOD = 998244353;
int q_pow(int x,int y)
{
int res=1;
while(y)
{
if(y&1) res=res*x%MOD;
x=x*x%MOD;
y>>=1;
}
return res;
}//快速幂
signed main() {
int n;
cin >> n;
int mod = 998244353;
for (int i = 1; i <= n; i++) {
cin >> p[i];
}
// int ans = 0;
// mt[n-1] = p[n-1];
// for (int i = n-2; i >= 0; i--) {
// mt[i] = (mt[i+1])*p[i]%mod;
// }
// for (int i = 0; i < n; i++) {
// ans += mt[i];
// ans = ans%mod;
// }
// cout << ans << endl;
for (int i = 1; i <= n; i++) {
cout << q_pow(p[i],mod-2) << endl;
mt[i] = (mt[i-1]+1)*100%mod*q_pow(p[i],mod-2)%mod;
//后面那一坨是费马小定理,a好像就是p【i】的mod-2次方在余mod,不懂暂且记住
}//不理解但尊重过,好像是得多加一天?
cout << mt[n] << endl;
return 0;
}
D - 4/N
也就wa了六次吧,我真是听取wa声一片,而且一直只有几个点不过,后来把范围开大忽然就过了,题目给的范围太草率了吧
题解:
给出N,求解4/N=1/h+1/n+1/w,输出满足条件的一组h,n,w。
存在都小于3500并满足要求的解。
其实就是个二重循环,数字开大即可。
代码:
#include<iostream>
#include<algorithm>
#include<math.h>
#include<cmath>
#include<queue>
#include<stack>
using namespace std;
#define int long long
#define double long double
signed main() {
double n;
cin >> n;
for (int i = 1; i <= 4500; i++) {
for (int j = 1; j <= 4500; j++) {
//一开始开到3500,有几个点死活过不了
if(4*i*j > n*i+n*j) {
int w = (double)1/((double)4/n - (double)1/i - (double)1/j);
if (w > 0 && 4 * i * j * w == n * i * j + n * j * w + n * i * w) {
//保险起见,再判断一次。过了几个点
cout << i << ' ' << j << ' ' << w << endl;
return 0;
}
}
}
}
}
E - Tree Destruction
题解:
每个红箱中有r个红球,绿箱中有g个绿球,蓝箱中有b个蓝球,求如何取箱子最终得到n个球。
二重循环判断即可,简单题。
代码:
#include<iostream>
#include<algorithm>
#include<math.h>
#include<cmath>
#include<queue>
#include<stack>
using namespace std;
#define int long long
signed main() {
int r,g,b,n;
cin >> r >> g >> b >> n;
int ans = 0;
for (int i = 0; i <= n/r+1; i++) {
for (int j = 0; j <= n/g+1; j++) {
int mt = n - i*r - j*g;
if(mt%b == 0 && mt/b >= 0){
// cout << i << ' ' << j << ' ' << mt/b << endl;
ans++;
}
}
}
cout << ans << endl;
return 0;
}
F - AB Substrings
题解:
n个字符串,可以互相连接,最后最多会出现多少个AB。
判断内部AB,和三组字符串分别的数量,然后推一下如何连接及其个数即可。
代码:
#include<iostream>
#include<algorithm>
using namespace std;
#define int long long
#define double long double
signed main() {
int n;
cin >> n;
int a=0,b=0,ab=0;
int ans = 0;
for (int i = 0; i < n; i++) {
string ls;
cin >> ls;
for (int j = 1; j < ls.size(); j++) {
if (ls[j] == 'B' && ls[j - 1] == 'A')ans++;
}
if (ls[ls.size() - 1] == 'A' && ls[0] == 'B') ab++;
else if (ls[ls.size() - 1] == 'A') a++;
else if (ls[0] == 'B') b++;
}
if(a == 0 && b == 0) {
if(ab != 0) {
ans += (ab-1);
}
}//一些特殊情况,有俩个点应该。因为只有ab,所以他们只能互相连,会有被浪费的但也没办法啦
else if(a <= b && a <= ab) {
ans = ans+a+ab;
}
else if(b <= a && b <= ab) {
ans = ans+b+ab;
}
else if(ab <= a && ab <= b) {
ans = ans + 2*ab + min(a-ab,b-ab);
}//这一部分是直接数学推出来的,有点晕了要
cout << ans << endl;
return 0;
}
G - DivRem Number
啊我要是早点发现你就好了,浪费了好多时间
题解:
给定n,求满足条件x的总和,要求n除以x与n模x的值相等。
从1开始遍历到sqrt即可,再往上不存在,数学思维推一下。
代码:
#include<iostream>
#include<algorithm>
#include<math.h>
using namespace std;
#define int long long
#define double long double
int p[200005];
int mt[200005];
signed main() {
int n;
cin >> n;
int t = sqrt(n);
int ans = 0;
for (int i = 1; i*i < n; i++) {
if(n % i == 0) {
int p = n/i-1;
if (n % p == n/p)
//有1,2这种特殊情况,必须再判断一次
ans += (n/i-1);
}
}
cout << ans << endl;
return 0;
}
H - Flat Subsequence
暂时不会,用到线段树与树状数组,还没学这个知识点。