昨天晚上打了一场很水很水的比赛,题目没有什么思维难度,总结一下经验吧:
|
A
发现了一个结论:令斐波那契数列的 ,则有
利用归纳法证明:
首先, 时肯定是符合的,有 ,那么我们只需要证明 时也符合。
于是再来看看 ……
卡西尼恒等式:
但这个东西真的是对的吗?
经过验证后,这个悖论明显是错的,因为右图的两个三角形并不相似:一个是 ,一个是 。
(学妹还剪纸验证了一下,拼不起来233)
C
数据随机……暴力可过。
E
最长不下降子序列的二分函数中,
应该从
开始,
因为如果序列中没有小于等于
的数,
应该放在
的位置。
int find(int x) {
int l = 0, r = len;
while (l < r) {
int mid = l + (r - l + 1 >> 1);
if (d[mid] <= x) l = mid;
else r = mid - 1;
}
return l;
}
F
题目大意:给出一个长度为 的序列,你需要计算出所有长度为 的子序列中,除最大最小数之外所有数的乘积相乘的结果,答案对 取模。
很显然将原序列从小到大排好序后,答案应该为
但指数不可以直接取模,考虑模数是一个质数,有
而当 不是质数的时候,我们有
——扩展欧拉定理
考虑如何证明 ,我们有
其中
假设模数 (素数的幂), ,显然
若 ,那么 ,所以
若 ,则 ,显然 和 的指数均大于等于 ,所以
对于任意模数,均可唯一分解成若干素数的乘积,根据最上面的同余方程组可知, 对任意 成立。
#include <cstdio>
#include <algorithm>
const int N = 1005, P = 1000000007;
int C[N][N], a[N];
int read() {
int x = 0, f = 1;
char c = getchar();
while (c < '0' || c > '9') {
if (c == '-') f = -1;
c = getchar();
}
while (c >= '0' && c <= '9') {
x = (x << 3) + (x << 1) + (c ^ 48);
c = getchar();
}
return x * f;
}
void pre() {
C[0][0] = 1;
for (int i = 1; i <= 1000; ++i) {
C[i][0] = 1;
for (int j = 1; j <= i; ++j)
C[i][j] = (C[i-1][j] + C[i-1][j-1]) % (P - 1);
}
}
int pow(int a, int b) {
int res = 1;
for (; b; b >>= 1, a = 1LL * a * a % P)
if (b & 1) res = 1LL * res * a % P;
return res;
}
int main() {
pre();
int T = read();
while (T--) {
int n = read(), k = read(), ans = 1;
for (int i = 1; i <= n; ++i) a[i] = read();
if (n < 3) { puts("0"); continue; }
std::sort(a + 1, a + n + 1);
for (int i = 2; i < n; ++i) {
ans = 1LL * ans * pow(a[i], ((C[n-1][k-1] - C[i-1][k-1] - C[n-i][k-1]) % (P - 1) + (P - 1)) % (P - 1)) % P;
}
printf("%d\n", (ans + P) % P);
}
return 0;
}
时间复杂度 。