A 点对最大值
求这个树的直径,已经见过三次了,还是没打出来,注意个别地方稍微修改一下。
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <queue>
#include <cmath>
#include <string>
#include <vector>
#include <stack>
#include <map>
#include <sstream>
#include <cstring>
#include <set>
#include <cctype>
#include <bitset>
#define IO \
ios::sync_with_stdio(false); \
// cin.tie(0); \
// cout.tie(0);
using namespace std;
typedef long long LL;
const int maxn = 1e6 + 100;
const int maxm = 1e6 + 10;
const LL INF = 0x3f3f3f3f3f3f3f3f;
const int inf = 0x3f3f3f3f;
const LL mod = 1e9 + 7;
int dis[8][2] = {0, 1, 1, 0, 0, -1, -1, 0, 1, -1, 1, 1, -1, 1, -1, -1};
struct Edge
{
int before, to, w;
} e[maxn << 1];
int val[maxn], dp[maxn];
int n, k, head[maxn];
int ans = 0;
void add(int u, int v, int w)
{
e[k].before = head[u];
e[k].to = v;
e[k].w = w;
head[u] = k++;
}
void DFS(int u, int fa)
{
dp[u] = val[u];
for (int i = head[u]; i != -1; i = e[i].before)
{
int v = e[i].to;
if (v == fa)
continue;
DFS(v, u);
ans = max(ans, dp[u] + dp[v] + e[i].w);
dp[u] = max(dp[u], dp[v] + e[i].w);
}
}
int main()
{
#ifdef ONLINE_JUDGE
#else
freopen("in.txt", "r", stdin);
// freopen("out.txt", "w", stdout);
#endif
IO;
int T;
scanf("%d", &T);
while (T--)
{
k = 0;
memset(head, -1, sizeof head);
scanf("%d", &n);
int x, y;
for (int i = 2; i <= n; i++)
{
scanf("%d %d", &x, &y);
add(x, i, y);
add(i, x, y);
}
for (int i = 1; i <= n; i++)
scanf("%d", &val[i]);
ans = -inf;
DFS(1, 0);
cout << ans << "\n";
}
return 0;
}
B 减成一
容易发现答案为每一个递增序列的递增差之和,可以把数组当做很多个递增序列(样例为3个递增序列为别递增 (2+2)+5+0=9),但是可能会出现第一个序列即为递减的情况,这时我们可以再在a[0] 位置设置一个1。这样就不需要特判了。
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <queue>
#include <cmath>
#include <string>
#include <vector>
#include <stack>
#include <map>
#include <sstream>
#include <cstring>
#include <set>
#include <cctype>
#include <bitset>
#define IO \
ios::sync_with_stdio(false); \
// cin.tie(0); \
// cout.tie(0);
using namespace std;
typedef long long LL;
const int maxn = 1e5 + 100;
const int maxm = 1e6 + 10;
const LL INF = 0x3f3f3f3f3f3f3f3f;
const int inf = 0x3f3f3f3f;
const LL mod = 998244353;
int dis[8][2] = {0, 1, 1, 0, 0, -1, -1, 0, 1, -1, 1, 1, -1, 1, -1, -1};
LL a[maxn];
int main()
{
#ifdef ONLINE_JUDGE
#else
freopen("in.txt", "r", stdin);
// freopen("out.txt", "w", stdout);
#endif
// IO;
int T;
int n;
scanf("%d", &T);
while (T--)
{
scanf("%d", &n);
for (int i = 1; i <= n; i++)
scanf("%lld", &a[i]);
a[0] = 1;
LL ans = 0;
for (int i = 1; i <= n; i++)
{
if (a[i] >= a[i - 1])
ans += 1LL * a[i] - a[i - 1];
}
cout << ans << endl;
}
return 0;
}
C 面积
水
D 扔硬币
这是一个基于二项分布情况下的简单的条件概率,把相对应的概率算出来就好。对于逆元要用线性递推进行预处理,否则T飞。哦对了,组合数也用了递推式,并没有逐个计算。
但是对于这道题目,只需要处理组合数就行,后面硬币概率算了就多此一举了,可惜我当时还是稀里糊涂得计算了。
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <queue>
#include <cmath>
#include <string>
#include <vector>
#include <stack>
#include <map>
#include <sstream>
#include <cstring>
#include <set>
#include <cctype>
#include <bitset>
#define IO \
ios::sync_with_stdio(false); \
// cin.tie(0); \
// cout.tie(0);
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
const int maxn = 1e6 + 100;
const int maxm = 1e6 + 10;
const LL INF = 0x3f3f3f3f3f3f3f3f;
const int inf = 0x3f3f3f3f;
const LL mod = 1e9 + 7;
int dis[8][2] = {0, 1, 1, 0, 0, -1, -1, 0, 1, -1, 1, 1, -1, 1, -1, -1};
LL c[maxn];
LL inv[maxn];
LL qpow(LL a, LL b, LL c)
{
LL ans = 1;
while (b)
{
if (b & 1)
ans = ans * a % c;
a = a * a % c;
b = b >> 1;
}
return ans;
}
LL Inv(LL a, LL p)
{
return qpow(a, p - 2, p);
}
int main()
{
#ifdef ONLINE_JUDGE
#else
freopen("in.txt", "r", stdin);
// freopen("out.txt", "w", stdout);
#endif
// IO;
int T;
inv[1] = 1;
for (int i = 2; i <= maxn; i++)
{
inv[i] = mod - mod / i * inv[mod % i] % mod;
}
cin >> T;
while (T--)
{
LL n, m, k;
cin >> n >> m >> k;
if (k > n - m)
{
cout << 0 << endl;
continue;
}
m = n - m;
LL t1 = qpow(Inv(2, mod), n, mod); // 2 的 n次方
LL t2 = Inv(k, mod); // k 的 逆元
c[0] = 1;
LL ans2 = c[0] * t1 % mod;
for (int i = 1; i <= m; i++)
{
c[i] = ((c[i - 1] % mod * (n - i + 1) % mod) * inv[i] % mod) % mod;
ans2 = (ans2 % mod + c[i] * t1 % mod) % mod;
}
LL ans1 = c[k] * t1 % mod;
cout << ans1 * Inv(ans2, mod) % mod << endl;
}
return 0;
}
E 赛马
O(n^)暴力即可,不要忘了标记。
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <queue>
#include <cmath>
#include <string>
#include <vector>
#include <stack>
#include <map>
#include <sstream>
#include <cstring>
#include <set>
#include <cctype>
#include <bitset>
#define IO \
ios::sync_with_stdio(false); \
// cin.tie(0); \
// cout.tie(0);
using namespace std;
typedef long long LL;
const int maxn = 1e5 + 100;
const int maxm = 1e6 + 10;
const LL INF = 0x3f3f3f3f3f3f3f3f;
const int inf = 0x3f3f3f3f;
const LL mod = 998244353;
int dis[8][2] = {0, 1, 1, 0, 0, -1, -1, 0, 1, -1, 1, 1, -1, 1, -1, -1};
bool vis[maxn];
int a[maxn], b[maxn];
int main()
{
#ifdef ONLINE_JUDGE
#else
freopen("in.txt", "r", stdin);
// freopen("out.txt", "w", stdout);
#endif
// IO;
int T;
int n;
cin >> T;
while (T--)
{
scanf("%d", &n);
for (int i = 1; i <= n; i++)
{
vis[i] = false;
scanf("%d", &a[i]);
}
for (int i = 1; i <= n; i++)
scanf("%d", &b[i]); // 对手
sort(a + 1, a + n + 1);
int ans = 0;
for (int i = 1; i <= n; i++)
{
int t = b[i];
int flag = false;
for (int j = 1; j <= n; j++)
{
if (a[j] > t && vis[j] == false)
{
flag = true;
vis[j] = true;
break;
}
}
if (flag)
ans++;
}
cout << ans << endl;
}
return 0;
}
F 三角形
这题当时懵了,这么多人做出来,就该再仔细思考一下的。
斐波那契数列对于这题是最完美的,假如给定的长度不满足斐波那契前n项和,那么直接加到最后一条边上,具体看代码。
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <queue>
#include <cmath>
#include <string>
#include <vector>
#include <stack>
#include <map>
#include <sstream>
#include <cstring>
#include <set>
#include <cctype>
#include <bitset>
#define IO \
ios::sync_with_stdio(false); \
// cin.tie(0); \
// cout.tie(0);
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
const int maxn = 1e6 + 100;
const int maxm = 1e6 + 10;
const LL INF = 0x3f3f3f3f3f3f3f3f;
const int inf = 0x3f3f3f3f;
const LL mod = 1e9 + 7;
int dis[8][2] = {0, 1, 1, 0, 0, -1, -1, 0, 1, -1, 1, 1, -1, 1, -1, -1};
ULL f[200];
int main()
{
#ifdef ONLINE_JUDGE
#else
freopen("in.txt", "r", stdin);
// freopen("out.txt", "w", stdout);
#endif
// IO;
f[1] = 1;
f[2] = 1;
for (int i = 3; i <= 200; i++)
{
f[i] = f[i - 1] + f[i - 2];
if (f[i] < f[i - 1])
break;
}
int T;
ULL a;
cin >> T;
while (T--)
{
cin >> a;
for (int i = 1; i <= 93; i++)
{
if (a > f[i])
a -= f[i];
else if (a == f[i])
{
cout << i << endl;
break;
}
else if (a < f[i])
{
cout << i - 1 << endl;
break;
}
}
}
return 0;
}
G 养花
最大流,建图很多地方不明白,待定。
H 直线
由公式可得答案为 n*(n-1)/2 python水过。。
n = int(input())
for i in range(n):
m = int(input())
print(m * (m-1) // 2)
I 字典序
待定。
J 最大值
可以把输入的s当做模式串,s去掉第一个字符做为文本串,进行kmp匹配,维护一个匹配的最大长度,这样就满足题意了,题解说直接求next数组??我还是tcl!!
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <queue>
#include <cmath>
#include <string>
#include <vector>
#include <stack>
#include <map>
#include <sstream>
#include <cstring>
#include <set>
#include <cctype>
#include <bitset>
#define IO \
ios::sync_with_stdio(false); \
// cin.tie(0); \
// cout.tie(0);
using namespace std;
typedef long long LL;
const int maxn = 1e6 + 100;
const int maxm = 1e6 + 10;
const LL INF = 0x3f3f3f3f3f3f3f3f;
const int inf = 0x3f3f3f3f;
const LL mod = 1e9 + 7;
int dis[8][2] = {0, 1, 1, 0, 0, -1, -1, 0, 1, -1, 1, 1, -1, 1, -1, -1};
string s, p;
int nextp[maxn];
void Get_nextp(int n)
{
for (int i = 1; i < n; i++)
{
int j = i;
while (j > 0)
{
j = nextp[j];
if (p[i] == p[j])
{
nextp[i + 1] = j + 1;
break;
}
}
}
}
int Kmp(int n)
{
int i, j;
int ans = -1;
for (i = 0, j = 0; i < n; i++)
{
if (j < n && s[i] == p[j])
j++, ans = max(ans, j);
else
{
while (j > 0)
{
j = nextp[j];
if (s[i] == p[j])
{
j++;
ans = max(ans, j);
break;
}
}
}
}
return ans;
}
int main()
{
#ifdef ONLINE_JUDGE
#else
freopen("in.txt", "r", stdin);
// freopen("out.txt", "w", stdout);
#endif
IO;
int T, n;
cin >> T;
while (T--)
{
cin >> s;
n = s.size();
p = s.substr(1, n - 1);
swap(s, p);
// cout << s << endl;
// cout << p << endl;
Get_nextp(n);
cout << Kmp(n - 1) << endl;
}
return 0;
}