一、F题(签到)对答案一时爽
#include<iostream> #include<algorithm> #include<cmath> #include<cstring> using namespace std; typedef long long ll; char aa[110]; char bb[110]; int main() { int n; cin >> n; for (int i = 0; i < n; i++)cin >> aa[i]; for (int i = 0; i < n; i++)cin >> bb[i]; int cou = 0; for (int i = 0; i < n; i++) { if (aa[i] == bb[i])cou++; } int p1 = n + cou; int p2 = 0; cout << p1 << " " << p2 << endl; }
二、B题 括号
链接:https://ac.nowcoder.com/acm/contest/9981/B
题目描述
请你构造一个非空的括号字符串,包含正好 kkk 个不同合法括号对。
所谓括号字符串,是指由'('和')'这两种字符构成的字符串。
要求构造的字符串长度不超过100000。
输入描述:
一个整数 k。
k小于10^9.
输出描述:
一个仅包含左右括号字符串,其中有 k个合法的括号对。如果有多种构造方法,输出任意一种合法即可。
理解:WA一次,是没有看到字符串不能超过10^5,后来想到卡长度应该不会超,所以我就想直接对半分,左边全部都是 ( ,右边全部都是 ) ,其他的从后面数过来,只要再添加一个(。
#include<iostream> #include<algorithm> #include<cmath> #include<cstring> using namespace std; typedef long long ll; int main() { int k; cin >> k; if (k < 99999) { cout << "("; for (int i = 0; i < k; i++)cout << ")"; cout << endl; } else { int p = k / 50000; int pp = k % 50000; for (int i = 0; i < p; i++)cout << "("; int ppp = 50000 - pp; for (int i = 0; i < ppp; i++)cout << ")"; cout << "("; //cout << p << " " << pp << " " << ppp << endl; for (int i = 0; i < pp; i++)cout << ")"; } }
三、I题 限制不互素对的排列(中思维)
链接:https://ac.nowcoder.com/acm/contest/9981/I
题目描述 :输入一个数 ,请构造一个长度为 n 的排列,使得其中正好有 k 对相邻的数gcd(最大公约数)大于1 。
排列是指 1到 n 一共 n 个数,每个数都出现过且仅出现过 1 次。n<10^5,0<k<n/2.
输入描述:
两个整数 n 和 k ,用空格隔开。
输出描述:
如果不存在可行的构造方案,输出-1。
否则输出一行 n个数符合的排列,用空格隔开。如果有多组可行的构造方案,输出任意一组即可。
理解:取巧,0<k<n/2,只要想到k的范围的含义,就能够想出来,全部都都是2的倍数不就可以破解很多了。
#include<iostream> #include<algorithm> #include<cmath> #include<cstring> using namespace std; typedef long long ll; int n, k; int aa[100010]; int main() { cin >> n >> k; if (k == n / 2){ if (n < 6)cout << -1 << endl; else { for (int i = 2; i <= 2 * k; i = i + 2) { if (i == 6)continue; cout << i << " "; aa[i] = 1; } aa[6] = 1; aa[3] = 1; cout << 6 << " " << 3 << " "; for (int i = 1; i <= n; i++) { if (aa[i] == 0)cout << i << " "; } } } else { for (int i = 2; i <= 2 * (k+1); i = i + 2) { cout << i << " "; aa[i] = 1; } for (int i = 1; i <= n; i++) { if (aa[i] == 0)cout << i << " "; } } }
四、A题 串(组合数学)
链接:https://ac.nowcoder.com/acm/contest/9981/A
题目描述 : 长度不超过n,且包含子序列“us”的、只由小写字母构成的字符串有多少个? 答案对10^9+7取模。
所谓子序列,指一个字符串删除部分字符(也可以不删)得到的字符串。
例如,"unoacscc"包含子序列"us",但"scscucu"则不包含子序列"us"
输入描述:一个正整数n(2≤n≤10^6 )
输出描述:一个正整数,为满足条件的字符串数量对10^9+7取模的值
输入
3
输出
77
说明
长度为3的字符串里,
形状是"u?s"的共有26个
形状是"?us"的共有26个
形状是"us?"的共有26个。
但是,"uss"和"uus"被各多计算了1次,应该减去,
所以共有26*3-2=76个。
再加上长度为2的"us",所以长度不超过3的合法字符串共有77个。
示例3
输入
874520
输出
16471619
理解1:(状态DP)
既然我们需要前i-1个有u没有s的,就把所有点情况都放在状态里, f[i][0/1/2]表示长度为i的 **没有u的串/有u但是u后面没有s的串/有us的串的数量**

#include<iostream> #include<algorithm> #include<cmath> #include<cstring> using namespace std; typedef long long ll; int n; ll f[1000100][4]; const int mod = 1e9 +7; int main() { ll ans = 0; cin >> n; f[1][0] = 25; f[1][1] = 1; f[1][2] = 0; for (int i = 2; i <= n; i++) { f[i][0] = (f[i - 1][0] * 25) % mod; f[i][1] = (f[i - 1][1] * 25 + f[i - 1][0]) % mod; f[i][2] = (f[i - 1][1] + f[i - 1][2] * 26) % mod; ans = (ans + f[i][2]) % mod; } cout << ans ; }
理解2:(组合数学)

#include<iostream> #include<algorithm> #include<cmath> #include<cstring> using namespace std; typedef long long ll; int n; ll f[1000009];//数组也要是long const int mod = 1e9 +7; ll qu(ll a, ll b) { ll res = 1; while (b) { if (b & 1)res = res * a % mod; a = a * a % mod; b >>= 1; } return res ; } int main() { cin >> n; ll res = 1; f[2] = 1; for (int i = 3; i <= n; i++) { f[i] = (f[i - 1] * 25 % mod + qu(26, i - 1)) % mod; f[i] = f[i] - qu(25, i - 1); if (f[i] < 0)f[i] = f[i] + mod;//注意:要加上取模 res = ( res + f[i]) % mod; } cout << res; }
#include<iostream> #include<algorithm> #include<cmath> #include<cstring> using namespace std; typedef long long ll; int n; ll aa[1000100]; const int mod = 1e9 +7; ll qu(ll a, ll b) { ll res = 1; while (b) { if (b & 1)res = res * a % mod; a = a * a % mod; b >>= 1; } return res; } int main() { scanf("%d", &n); aa[2] = 1; aa[3] = 77; for (int i = 3; i <= n; i++) { aa[i] = (qu(26, i - 1) - qu(25, i - 1) + 25 * aa[i - 1]) % mod; if(aa[i]<0)aa[i]+=mod;//就是这里导致我写的过不了 } ll ans = 0; for (int i = 2; i <= n; i++) { ans = (ans + aa[i]) % mod; } ans = ans % mod; printf("%d", ans); }
五、三棱锥之刻(计算几何,正三棱锥)
链接:https://ac.nowcoder.com/acm/contest/9981/E
牛牛站在一个棱长为的正三棱锥内部的中心。(牛牛是不可移动的)
(所谓正三棱锥,指六条棱都相等的三棱锥。正三棱锥的中心指到 4 个顶点距离都相等的那个点)
如上图,,牛牛站在P点,
他拿着一个染色喷雾,可以用来给正三棱锥的内表面染色。
已知喷雾能喷洒的距离为。也就是说,三棱锥内表面距离牛牛不超过的点才有可能被染色。牛牛想知道,正三棱锥内表面能被他染色的最大面积是多少?
ps:牛牛可看成一个无大小的点。重力对于喷雾的影响忽略不计。
输入描述:两个正整数和
1≤a,r≤1000
输出描述:染色的最大面积。若你的答案和正确答案误差不超过10^-3,则认为你的答案正确。
示例1
输入
1 1
输出
1.73205
说明:正三棱锥棱长为 1 ,且喷雾的有效射程为 1 ,易知牛牛可以将喷雾喷满整个内表面,即结果为整个内表面的面积。
理解:正三棱锥:内切球半径 r =a*(根号6)/12 外接球半径 R = a*(根号6)/4 中心到面的距离 H=a*(根号3)/6 扇形面积 S=0.5*弧度*直线长*直线长
#include<iostream> #include<algorithm> #include<cmath> #include<set> #include<cstring> using namespace std; typedef long long ll; const int maxn = 1e6 + 7; const double pi = acos(-1);//3.14159 //3.1415926535 897932384626 43383279502 88419716939937 // 5105820974944592307 8164062862089986 2803482534211706798 double cal(double a, double b, double c) { double tmp = (a * a + b * b - c * c) / (2 * a * b); return acos(tmp); } double a, r; int main() { cin >> a >> r; double minr = sqrt(6) / 12 * a;//内切球半径 double maxr = sqrt(6) / 4 * a;//外接球半径 double ans = 0; if (r <= minr)ans = 0.0; else if (r >= maxr)ans = a * a * sqrt(3); else { double R = sqrt(r * r - minr * minr);//三角形染色的圆的半径 double h = sqrt(3) / 6 * a;//正三角形的内圆半径,高的1/3 if (R <= h)ans = 4 * (pi * R * R); else { //R比较大的时候,超过h,小于maxr的时候圆只有一部分在染色 //所以先求出整个圆的面积,减去大扇形面积,加会大扇形里面的三角形面积 //求三角形DEJ的大角弧度,EJ就是mn ans = pi * R * R; double mn = 2 * sqrt(R * R - h * h); double hudu = cal(R, R, mn);//弧度 ans -= 3 * (0.5 * hudu * R * R);//扇形面积 ans += 3 * (0.5 * R * R * sin(hudu));//正弦定理 ans *= 4; } } cout << ans << endl; }
浙公网安备 33010602011771号