F.对答案一时爽
题解:
签到题,直接去看两个人的成绩是否相同,相同+2
不同则+1
AC代码:
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<vector>
#include<map>
#include<stack>
#include<queue>
#include<bitset>
#include<list>
#include<set>
#include<limits.h>
#define ll long long
#define INF 0x3f3f3f3f
#define inf -INF
#define me(a,b) memset(a,b,sizeof(a))
#define PII pair<int,int>
#define ull unsigned long long
#define ios std :: ios :: sync_with_stdio(false)
#define esp 1e-16
using namespace std;
const int maxn = 1e4 + 19;
int n,ans = 0;
char a[maxn],b[maxn];
int main()
{
ios;
cin >> n;
for(int i = 0;i < n;i ++) cin >> a[i];
for(int i = 0;i < n;i ++) cin >> b[i];
for(int i = 0;i < n;i ++) {
if(a[i] == b[i]) ans ++;
else continue;
}
cout << ans + n << ' ' << 0 << endl;
return 0;
}
B.括号
题解:
首先很容易想到对于平方数我们可以直接写成((()))
这样子的形式,而且这个字符串的长度一定是最小的,长度为
2
n
2 \sqrt{n}
2n
那么我们肯定是想在这个最小长度的基础上去凑剩下的非平方数,其实只要在最左边的括号后面加右括号匹配就可以了。
比如说这样:
(
(
(
)
)
)
→
9
,
(
)
(
(
)
)
)
→
10
((())) \rarr9,()(()))\rarr10
((()))→9,()(()))→10
我们就只需要找出它的基础组成的完全平方数是哪一个就可以了。
AC代码:
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<vector>
#include<map>
#include<stack>
#include<queue>
#include<bitset>
#include<list>
#include<set>
#include<limits.h>
#define ll long long
#define INF 0x3f3f3f3f
#define inf -INF
#define me(a,b) memset(a,b,sizeof(a))
#define PII pair<int,int>
#define ull unsigned long long
#define ios std :: ios :: sync_with_stdio(false)
#define esp 1e-16
using namespace std;
const int mode = 1e9 + 7;
int main()
{
ios;
int k;
cin >> k;
if(k == 0){
cout << ")" << endl;
return 0;
}
int m = floor((sqrt(k))),n = k - m * m;
if(m * m == k) {
for(int i = 0;i < m;i ++) cout << '(';
for(int i = 0;i < m;i ++) cout << ")";
cout << endl;
}
else {
if(n < m) {
cout << '(';
for(int i = 0;i < n;i ++) cout << ")";
for(int i = 0;i < m - 1;i ++) cout << "(";
for(int i = 0;i < m;i ++) cout << ")";
cout << endl;
}
else {
for(int i = 0;i < m;i ++) cout << "(";
for(int i = 0;i < m;i ++) cout << ")";
for(int i = 0;i < n - m;i ++) cout << "(";
cout << ")";
cout << endl;
}
}
return 0;
}
I.限制不互素对的排列
题解:
这个题目的突破口主要就是这个
k
∈
[
0
,
n
2
]
k \in [0,\frac{n}{2}]
k∈[0,2n]
我们可以发现,如果是有n个数,且有
n
⩾
9
n \geqslant 9
n⩾9,那么我们把所有的偶数拿出来就一定是有
2
n
−
1
2n - 1
2n−1对合法,那么剩下的一对我们就可以直接拿3,9凑。
如果是
n
<
9
n < 9
n<9,其实可以直接硬讨论写答案了,注意一下8
,3
的组合需要写成2 4 6 3 1 5
AC代码:
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<vector>
#include<map>
#include<stack>
#include<queue>
#include<bitset>
#include<list>
#include<set>
#include<limits.h>
#define ll long long
#define INF 0x3f3f3f3f
#define inf -INF
#define me(a,b) memset(a,b,sizeof(a))
#define PII pair<int,int>
#define ull unsigned long long
#define ios std :: ios :: sync_with_stdio(false)
#define esp 1e-16
using namespace std;
const int maxn = 1e6 + 19;
int a[maxn],n,k;
map<int ,int> mp;
int main()
{
ios;
bool flag = 1;
int cnt = 0;
mp.clear();
cin >> n >> k;
if(k == 0) {
for(int i = 1;i < n;i ++) cout << i << ' ';
cout << n << endl;
return 0;
}
if(n == 8 && k == 4) {
cout << "2 4 8 6 3 1 5 7" << endl;
return 0;
}
if((n == 2 && k == 1) || (n == 3 && k == 1) || (n == 4 && k == 2) || (n == 5 && k == 2)) {
cout << -1 << endl;
return 0;
}
int t = 2;
while(t <= n) {
a[++cnt] = t;
t += 2;
}
if(cnt - 1 >= k) {
cout << a[1];
mp[a[1]] = 1;
int sum = 1;
for(int i = 2;i <= cnt;i ++) {
sum ++;
if(sum - 1 < k){
cout << ' ' << a[i];
mp[a[i]] = 1;
}
else if(sum - 1 == k) {
cout << ' ' << a[i];
mp[a[i]] = 1;
break;
}
}
for(int i = 1;i <= n;i ++) if(!mp[i]) cout << ' ' << i;
cout << endl;
}
else if(cnt - 1 < k) {
cout << a[1];
mp[a[1]] = 1;
for(int i = 2;i <= cnt;i ++) {
cout << ' ' << a[i];
mp[a[i]] = 1;
}
if(n < 9) {
cout << " 3";
mp[3] = 1;
}
else {
cout << " 3 9";
mp[3] = mp[9] = 1;
}
for(int i = 1;i <= n;i ++) if(!mp[i]) cout << ' ' << i;
cout << endl;
}
return 0;
}
A.串
题解:
dp。
我们定义状态
d
p
[
i
]
[
0
/
1
/
2
]
dp[i][0/1/2]
dp[i][0/1/2]表示长度为i
的字符中无us
/有u
/有us
三种状态。
然后我们写出他的状态转移方程:
d
p
[
i
]
[
0
]
=
d
p
[
i
−
1
]
[
0
]
∗
25
dp[i][0] = dp[i - 1][0] * 25
dp[i][0]=dp[i−1][0]∗25
d
p
[
i
]
[
1
]
=
d
p
[
i
−
1
]
[
0
]
∗
1
+
d
p
[
i
−
1
]
[
1
]
∗
25
dp[i][1] = dp[i - 1][0] * 1 + dp[i - 1][1] * 25
dp[i][1]=dp[i−1][0]∗1+dp[i−1][1]∗25
d
p
[
i
]
[
2
]
=
d
p
[
i
−
1
]
[
1
]
∗
1
+
d
p
[
i
−
1
]
[
2
]
∗
26
dp[i][2] = dp[i - 1][1] * 1 + dp[i - 1][2] * 26
dp[i][2]=dp[i−1][1]∗1+dp[i−1][2]∗26
只要最后把
d
p
[
i
]
[
2
]
dp[i][2]
dp[i][2]累加就OK了
时间复杂度
O
(
n
)
O(n)
O(n)
AC代码:
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<vector>
#include<map>
#include<stack>
#include<queue>
#include<bitset>
#include<list>
#include<set>
#include<limits.h>
#define ll long long
#define INF 0x3f3f3f3f
#define inf -INF
#define me(a,b) memset(a,b,sizeof(a))
#define PII pair<int,int>
#define ull unsigned long long
#define ios std :: ios :: sync_with_stdio(false)
#define esp 1e-16
using namespace std;
const int maxn = 1e6 + 19;
const int mode = 1e9 + 7;
int n;
ll dp[maxn][3];
int main()
{
ios;
cin >> n;
dp[1][0] = 25;
dp[1][1] = 1;
dp[1][2] = 0;
ll ans = 0;
for(int i = 2;i <= n;i ++) {
dp[i][0] = (dp[i - 1][0] * 25) % mode;
dp[i][1] = (dp[i - 1][0] * 1 + dp[i - 1][1] * 25) % mode;
dp[i][2] = (dp[i - 1][1] * 1 + dp[i - 1][2] * 26) % mode;
ans = (ans + dp[i][2]) % mode;
}
cout << ans << endl;
return 0;
}
E.三棱锥之刻
题解:
emmmmm理论上就是高中数学知识。
讨论一下不同半径的截面形状和大小即可。
其实感觉用python
更简单。
import math as ma
a,R = map(int,input().split())
h = ma.sqrt(6) * a / 12
DP = ma.sqrt(3) * a / 6
AD = ma.sqrt(3) * a / 3
r = ma.sqrt(R * R - h * h) if R >= h else 0
ans = 0.0
if R <= h:
ans = 0.0
elif r <= DP :
ans = ma.pi * 4 * r * r
elif r >= AD :
ans = a * a * ma.sqrt(3)
else :
A = ma.asin(DP / r)
l = ma.sqrt(r * r - DP * DP)
ans = 3 * DP * l + 0.5 * r * r * (2 * A - ma.pi / 3) * 3
ans *= 4
print(ans)
J.一群小青蛙呱蹦呱蹦呱
题解:
数学+贪心
肯定是找多个素数组合的数然后求
l
c
m
lcm
lcm
首先我们需要有一个数学知识的储备:
对于任何一个正整数,我们都可以写成这样的表达形式:
X
=
P
1
n
1
P
2
n
2
P
3
n
3
.
.
.
.
.
.
P
m
n
m
X = P_1^{n_1}P_2^{n_2}P_3^{n_3}......P_m^{n_m}
X=P1n1P2n2P3n3......Pmnm
其中
P
i
P_i
Pi是素数
对于两个数的
l
c
m
lcm
lcm,我们其实就可以把两个数分解以后取对应质因子的最大系数值。
换句话说,我们就是求
n
i
n_i
ni的最大值然后最后得到答案:
a
n
s
=
∏
1
≤
i
≤
m
p
i
n
i
%
m
o
d
e
ans = \prod_{\mathclap{1\le i\le m}} {p_i}^{n_i} \enspace \% \enspace mode
ans=1≤i≤m∏pini%mode
对于
p
i
n
i
{p_i}^{n_i}
pini的计算我们当然可以直接使用快速幂求出。
现在的问题就是如何就求解对于每个
P
i
P_i
Pi的最大的
n
i
{n_i}
ni。
这里就需要贪心了
我们对于这些质数因子,我们考虑当
p
i
=
2
p_i =2
pi=2的时候,最大的系数是就是当前只有2,3两个素数组成时,同理对于其他的值,最大的系数就是当前只有2和它两个素数组成时。
那么自然就是有这样的式子:
n
i
=
{
p
o
w
(
2
,
l
o
g
(
n
3
)
l
o
g
(
2
)
)
if
p
i
=
2
p
o
w
(
x
,
l
o
g
(
n
2
)
l
o
g
(
x
)
)
if
p
i
≠
2
n_i = \begin{cases} pow(2,\frac{log(\frac{n}{3})}{log(2)}) &\text{if \enspace} p_i = 2\\ pow(x,\frac{log(\frac{n}{2})}{log(x)}) &\text{if \enspace} p_i \not= 2 \end {cases}
ni={pow(2,log(2)log(3n))pow(x,log(x)log(2n))if pi=2if pi=2
所以我们可以用
O
(
n
)
O(n)
O(n)的复杂度去打表,这里需要一个埃式筛。然后我们又发现其实不用把这
n
n
n个数全部打表,因为可能保留下来的最大的素数就是
n
2
\frac{n}{2}
2n,所以只需要打一个
8
e
7
8e7
8e7的表就可以了。
AC代码:
#pragma warning(disable:4996)
#define _CRT_SECURE_NO_WARNINGS
#include<bits/stdc++.h>
#define ll long long
#define INF 0x3f3f3f3f
#define inf -0x3f3f3f3f
#define me(a,b) memset(a,b,sizeof(a))
#define PII pair<int,int>
#define ull unsigned long long
#define ios std :: ios :: sync_with_stdio(false)
#define rep(i,a,b) for(int i = a;i <= b;i ++)
#define esp 1e-16
using namespace std;
const int maxn = 8e7 + 3;
const int mode = 1e9 + 7;
int n,cnt;
int prime[maxn],v[maxn],vis[maxn];
void Prime(int x) //埃式筛打表
{
me(v, 0);
me(vis, 0);
cnt = 0;
rep(i,2,x) {
if (v[i] == 0) {
v[i] = i;
prime[++cnt] = i;
vis[i] = 1;
}
rep(j,1,cnt) {
if (prime[j] > v[i] || prime[j] > x / i) break;
v[i * prime[j]] = prime[j];
}
}
return;
}
ll q_pow(int a, int b) //带模快速幂
{
ll res = 1;
while (b) {
if (b & 1) res = res * a % mode;
a = a * a % mode;
b >>= 1;
}
return res;
}
ll calc(int x)
{
if (x == 2) return q_pow(2, floor(log(n / 3) / log(x)));
else return q_pow(x, floor(log(n / 2) / log(x)));
}
int main()
{
ios;
cin >> n;
if (n <= 5) {
cout << "empty" << endl;
return 0;
}
Prime(n / 2);
ll ans = 1;
rep(i,2,n / 2) {
if (vis[i]) ans = (ans * calc(i)) % mode;
//cout << "ANS = " << ans << endl;
}
cout << ans << endl;
return 0;
}