2022.11.16 模拟赛总结
2022.11.16 模拟赛总结
\(T1\) 看起来对于我不是很可做,就大概看了一下 \(50\) 的做法,然后光速跳到 \(T2\), \(T2\) 打了个表把规律看出来了,然后又套了个组合意义,大概 \(15min\) 就切了,不过没注意 \(2\) 倍空间,挂了 \(60pts\)。\(T3\),\(T4\)感觉暴力都不可打,就去看的 \(T1\),想了大概一个小时,没思路,就去打的后面的暴力。还是要注意到细节,数组空间要给够,但是不要 \(MLE\),不要压着上线开空间,写代码注意到细节,不要一处改了,另一处不改。
\(T1\)
题目大意:在二维平面上有 \(n\) 个点,每个点的范围开始都是半径为 \(1\) 的圆,并且每秒以 \(1\) 个单位长度的速度增长,给定起始点,终点,问最晚什么时候出发,在到达终点时,不碰到任何一个圆。
我们不难发现因为移动速度和增长速度是一样的,并且只能上下左右移动,那么我们当且仅当在终点时碰到,那么一定就不行,所以只需要找到起点与终点的哈密顿距离然后进行判断即可。
\(T2:40pts\)
贴个链接吧
\(40pts\) 的做法还是很好想的,我们可以 \(O(n^2)\) 的做法求出 \((1,1)\) 到所有点的方案数,对于路径的花费我们打一个表可以不难发现到每个点的花费是固定的。所以不难求出到每个点的所有方案的花费。那么我们如何进行优化呢?我们想到将求方案数降到 \(O(nlogn)\) 或者 \(O(n)\)。我们考虑组合意义,我们到 \((n,m)\) 的步数是固定的,我们考虑第几步在 \(x\) 轴走,就转化成在 \((n + m - 2)\) 个数里选 \((n - 1)\) 个数的组合数。
点击查看代码
#include<bits/stdc++.h>
#define int long long
const int M = 1e6 + 7 , mod = 1e9 + 7;
int fac[M] , inv[M];
inline int Pow(int a , int b) {
int ans = 1;
while(b) {
if(b & 1) ans = ans * a % mod;
a = a * a % mod;
b >>= 1;
}
return ans ;
}
inline int C(int n , int m) {
if(n < 0 || m < 0 || n < m) return 0;
return fac[n] * inv[m] % mod * inv[n - m] % mod;
}
inline void swap(int &a , int &b) {
int t = a;
a = b , b = t;
}
signed main () {
// freopen("count.in","r",stdin);
// freopen("count.out","w",stdout);
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr),std::cout.tie(nullptr);
fac[0] = inv[0] = 1;
for(int i = 1; i <= 1e6; ++ i) fac[i] = fac[i - 1] * i % mod;
for(int i = 1; i <= 1e6; ++ i) inv[i] = Pow(fac[i] , mod - 2);
int t; std::cin >> t;
while(t --) {
int n , m; std::cin >> n >> m;
if(n > m) swap(n , m);
int ans = (m - 1 + (n - 1) * m % mod + mod) % mod * C(n + m - 2 , n - 1) % mod;
std::cout << ans << '\n';
}
}
\(T3 , T4\) 压根不会,润了……