比赛链接:
https://ac.nowcoder.com/acm/contest/11186
A.小y的平面
思路:
因为只能向右或者向上走,所以能走的下一个点只能在右上。
依据 x + y 的值对点进行一个排序(我没排序也过了,数据有点水),然后循环判断就可以了。
代码:
#include <bits/stdc++.h>
using namespace std;
#define all(x) (x).begin(), (x).end()
#define fi first
#define LL long long
#define pb push_back
#define PII pair <int, int>
#define se second
const int N = 1e6 + 10, M = 2e5 + 10;
const int mod = 1e9 + 7;
LL T = 1, n;
string s;
struct node{
int x, y;
}p[N];
bool cmp(node a, node b){
return a.x + a.y < b.x + b.y;
}
void solve(){
cin >> n;
for (int i = 1; i <= n; i++)
scanf("%d%d", &p[i].x, &p[i].y);
sort(p + 1, p + n + 1, cmp);
for (int i = 2; i <= n; i++)
if (p[i].x < p[i - 1].x || p[i].y < p[i - 1].y){
cout << "NO\n";
return;
}
cout << "YES\n";
}
int main(){
// cin >> T;
while(T--)
solve();
return 0;
}
B.小y的树
思路:
定义根节点为树的第 0 层,其子节点为第 1 层,那么这颗树总共有 \(n - 1\) 层,我们一层一层考虑。
根节点(即第 0 层)到所有节点的距离很好求,可以算出来是 \(\sum_{i = 0}^{n - 1} i * k^i\)。
接下来我们考虑第 1 层的一个节点到其它子节点的距离。
若设 \(t\) 为第 0 层节点到其它所有节点的距离和,而第 1 层的节点相比于第 0 层的节点,到 \(a\) 部分节点的距离减少了 1,到 \(b\) 部分节点的距离增加了 1,总距离的变化就是 \(a - b\)。
\(a\) 就是一个子树的总点数,可以通过循环去求解,那么 \(b\) 就是树的总点数减去 \(a\)。
这样子求出来了每个点到其他点的总距离之和,但是每条边我们计算了两次,所以最后结果要除 2,这里就要用到逆元,因为要先除后取模。
代码:
#include <bits/stdc++.h>
using namespace std;
#define LL long long
const int N = 1e6 + 10;
const int mod = 1e9 + 7;
LL T = 1, n, ans, k, sum, t, s[N];
LL qpow(LL a, LL b){
if (b == 0) return 1;
LL ans = 1;
while (b != 0){
if (b & 1) ans = (ans * a) % mod;
b >>= 1;
a = (a * a) % mod;
}
return ans;
}
LL inv(LL x, LL p){//逆元
return qpow(x, p - 2);
}
void solve(){
cin >> n >> k;
//sum 为点数的总和, t 为当前层的值
for (LL i = 0; i <= n - 1; i++){
LL l = qpow(k, i);
t = (t + (i * l) % mod) % mod;
sum = (sum + l) % mod;
s[i] = sum;
}
ans = t;
for (LL i = 2; i <= n; i++){
LL l = qpow(k, i - 1);
t = (t + (sum - (s[n - i] * 2) % mod + mod) % mod) % mod;
ans = (ans + (l * t % mod) % mod) % mod;
}
cout << (ans * inv(2, mod)) % mod << "\n";
}
int main(){
// cin >> T;
while(T--)
solve();
return 0;
}