A题 :Equivalent Prefixes
题意:就是给你两个有n个不同数的串,然后保证1-p区间内任选一个区间,使得区间中最小值的下标相同,找到最大的p值
思路:我的思路是设置两个单调栈,然后每次的第i个数判断大小,放到栈顶(比它大的数弹出栈),当两个栈容量不同时,即不成立。
代码如下:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 5e5 + 5;
int a[maxn], b[maxn];
stack<int>s1, s2;
int main(void)
{
int n;
while (~scanf("%d", &n)) {
for (int i = 1; i <= n; i++)
scanf("%d", &a[i]);
for (int i = 1; i <= n; i++)
scanf("%d", &b[i]);
while (s1.size()) s1.pop();
while (s2.size()) s2.pop();
int ans = 1;
s1.push(a[1]);
s2.push(b[1]);
for (int i = 2; i <= n; i++) {
while (s1.size() && s1.top() > a[i])
s1.pop();
s1.push(a[i]);
while (s2.size() && s2.top() > b[i])
s2.pop();
s2.push(b[i]);
if (s1.size() != s2.size())
break;
ans = i;
}
cout << ans << endl;
}
return 0;
} B题:Integration
题意:已知,求
这道题强行唤醒我的数学…但最终以失败告终…看了好几个巨巨的博客……这里感谢这位大佬的博客:2019牛客网暑期多校第一场B题
我们可以得到:
由数学归纳法,可得:
又因为
然后进行逆元,费马小定理
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod = 1e9 + 7;
const int maxn = 1e3 + 10;
ll a[maxn];
ll qpow(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(void)
{
int n;
while (~scanf("%d", &n)) {
for (int i = 1; i <= n; i++)
scanf("%lld", &a[i]);
ll ans = 0;
for (int i = 1; i <= n; i++) {
ll res = 1;
for (int j = 1; j <= n; j++) {
if (i == j)
continue;
res *= (a[j] * a[j] % mod - a[i] * a[i] % mod);
res %= mod;
}
ans += qpow(2 * a[i] % mod * res % mod, mod - 2);
}
ans = (ans % mod + mod) % mod;
cout << ans << endl;
}
} E题:ABBA
题意:有n个"AB",m个"BA",问能结合成多少个序列.这个要求是AB和BA的顺序不变,即A和B的相对位置不变,BA中可以穿插AB,反之亦然
那么我们采用dp,dp[i][j]表示放置i个A和j个B方案数
也就是说我们当前串也就是后面添加A还是添加B的情况
dp[i][j] += dp[i - 1][j]; dp[i][j] += dp[i][j - 1];
当i ≤ n时,A可以随便放;
当j ≤ m时,B可以随便放;
当i > n,如果放A,AB的数量要小于等于n,i - j是至少有多少个AB, i - j ≤ n;
当j > m,如果放B,BA的数量要小于等于m,j - i是至少有多少个BA, j - i ≤ m;
即
if(i - j <= n) d[i][j] += d[i - 1][j]; if(j - i <= m) d[i][j] += d[i][j - 1]];
最终代码如下(PS: 用于数据组过多,memset会卡T,跟缓冲区有关)
#include<bits/stdc++.h>
using namespace std;
const int mod = 1e9 + 7;
const int maxn = 2e3 + 10;
int dp[maxn][maxn];
int main(void)
{
int n, m;
while (~scanf("%d%d", &n, &m)) {
for (int i = 0; i <= n + m; i++)
for (int j = 0; j <= m + n; j++)
dp[i][j] = 0;
dp[0][0] = 1;
for (int i = 0; i <= n + m; i++) {
for (int j = 0; j <= m + n; j++) {
if (i - j < n)
dp[i + 1][j] = (dp[i][j] + dp[i + 1][j]) % mod;
if (j - i < m)
dp[i][j + 1] = (dp[i][j] + dp[i][j + 1]) % mod;
}
}
printf("%d\n", dp[n + m][n + m]);
}
return 0;
} F题:Random Point in Triangle
题意:求三角形内部一个点连三个顶点形成的最大三角形面积的期望,再乘一个36
答案是 11/2 倍三角形 ABC 的面积
#include<bits/stdc++.h>
using namespace std;
struct point{
long long x, y;
}a, b, c;
point AB, BC;
int main(void)
{
while (cin >> a.x >> a.y >> b.x >> b.y >> c.x >> c.y) {
AB.x = b.x - a.x;
AB.y = b.y - a.y;
BC.x = c.x - b.x;
BC.y = c.y - b.y;
printf("%lld\n",abs((AB.x * BC.y - AB.y * BC.x)) * 11);
}
return 0;
} J题 :Fraction Comparision
题意:判断x/a和y/b的大小,其中1 ≤ x, y ≤ 10<sup>18</sup>, 1 ≤ a, b ≤ 10<sup>9</sup>
签到题,这道题我们直接用的大整数写的,判断x * b和y * a,没什么好说的
其实出题人是想考察数学方面知识的,官方题解是这样的:
- 先把
写成
- 先比整数部分,分数部分分子分母都在 10<sup>9</sup> 范围内,交叉相乘比较
于是乎,上一下官方题解:
#include <bits/stdc++.h>
static std::pair<uint64_t, uint64_t> fcompare(uint64_t x, uint32_t a, uint64_t y, uint32_t b) {
uint64_t p = x / a; // p <= (x / a) < p + 1
uint64_t q = y / b; // q <= (y / b) < q + 1
if (p != q) {
return {p, q};
}
x %= a;
y %= b;
return {x * b, y * a};
}
int main(void)
{
std::ios::sync_with_stdio(false);
uint64_t x, y;
uint32_t a, b;
while (std::cin >> x >> a >> y >> b) {
auto result = fcompare(x, a, y, b);
if (result.first == result.second)
puts("=");
else if (result.first < result.second)
puts("<");
else
puts(">");
}
return 0;
} 
京公网安备 11010502036488号