(NOIP 2016 Day2) 模拟考试 题解报告
得分情况
(T1) (90 Pts)
(T2 45 Pts) ((Loj) 数据)
(T2 65 Pts) (洛谷 数据)
(T3 5 Pts)
总分: (140/160 Pts)
考试过程
(T1) 看一眼 组合数 数论 打表 看到杨辉三角 先写的递推 大概 (70) 然后看到 (k) 直接取模 能过 (90) 到 (95) 一个小时 先扔掉 去看 (T2) 对着数据点一个一个写 写完 (n^2) 的又把 (q = 0) 的单独拿出来 但是还是超时 大概不是很到一个小时 后面的时间死磕 (T3) 但并没有拿多少分
题解
(T1) 组合数问题
(O(n^2)) 预处理 + 二维前缀和优化把查询优化到 (O(1)) 就能过
代码
/*
Time: 6.15
Worker: Blank_space
Source:
*/
/*--------------------------------------------*/
#include<cstdio>
#include<cstring>
#define int long long
#define Min(x, y) ((x) < (y) ? (x) : (y))
/*--------------------------------------头文件*/
const int A = 1e4 + 7;
const int B = 1e5 + 7;
const int D = 1e7 + 7;
const int mod = 1e9 + 7;
const int INF = 0x3f3f3f3f;
/*------------------------------------常量定义*/
inline void File() {
freopen("problem.in", "r", stdin);
freopen("problem.out", "w", stdout);
}
/*----------------------------------------文件*/
int T, k, n, m, f[2021][2021], ans[2021][2021];
/*------------------------------------变量定义*/
inline int read() {
int x = 0, f = 1; char ch = getchar();
while(ch < '0' || ch > '9') {if(ch == '-') f = -1; ch = getchar();}
while(ch >= '0' && ch <= '9') {x = (x << 3) + (x << 1) + (ch ^ 48); ch = getchar();}
return x * f;
}
/*----------------------------------------快读*/
void work() {
n = read(); m = read();
printf("%lld
", ans[n][Min(n, m)]);
}
/*----------------------------------------函数*/
signed main() {
File();
T = read(); k = read(); f[0][0] = 1;
for(int i = 1; i <= 2000; i++)
{
for(int j = 1; j <= i; j++)
{
f[i][i - j] = f[i][j] = (f[i - 1][j - 1] + f[i - 1][j]) % k;
ans[i][j] = ans[i - 1][j] + ans[i][j - 1] - ans[i - 1][j - 1];
if(!f[i][j]) ans[i][j]++;
}
ans[i][i + 1] = ans[i][i];
}
while(T--) work();
return 0;
}
(T2) 蚯蚓
实际上写了 (70) 分的 复杂度大概是能卡过的 但是似乎由于优先队列的常数过大 后面的六个点就过了一个 吸氧的话分会高一些
同样没有吸氧的情况下 洛谷数据比 (LOJ) 的数据高 (20) 分 ...
正解
题中本身隐含单调性 先被切开的蚯蚓一定比后被切开的蚯蚓长 可以将两堆分别存储 每次切的时候从三堆中取最大的 切完依次放回 时间复杂度 (O(m))
维护三个队列 第一个表示原蚯蚓 第二个表示切开后较长的蚯蚓 第三个表示切开后较短的蚯蚓
先将原序列排序 省去每一秒增加每只蚯蚓的长度的操作 转换成在查询砍哪只蚯蚓时 把增加的长度算到蚯蚓的总长度上
每次在三个队列中找最长的 切开后放到二三里面
统计答案的时候将三个队列合并 排序输出
代码
/*
Time: 6.15
Worker: Blank_space
Source:
*/
/*--------------------------------------------*/
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#define Abs(x) ((x) < 0 ? -(x) : (x))
#define Max(x, y) ((x) > (y) ? (x) : (y))
#define Min(x, y) ((x) < (y) ? (x) : (y))
#define Swap(x, y) ((x) ^= (y) ^= (x) ^= (y))
/*--------------------------------------头文件*/
const int B = 1e5 + 7;
const int C = 8e6 + 7;
const int mod = 1e9 + 7;
const int INF = 0x3f3f3f3f;
/*------------------------------------常量定义*/
inline void File() {
freopen("earthworm.in", "r", stdin);
freopen("earthworm.out", "w", stdout);
}
/*----------------------------------------文件*/
int n, m, q, u, v, t, Q[3][C], l[3], r[3], a[C], cnt;
/*------------------------------------变量定义*/
inline int read() {
int x = 0, f = 1; char ch = getchar();
while(ch < '0' || ch > '9') {if(ch == '-') f = -1; ch = getchar();}
while(ch >= '0' && ch <= '9') {x = (x << 3) + (x << 1) + (ch ^ 48); ch = getchar();}
return x * f;
}
/*----------------------------------------快读*/
bool cmp(int x, int y) {return x > y;}
void work(int x) {
int id, y, z, max = 0;
if(l[0] <= r[0] && Q[0][l[0]] + x * q > max) max = Q[0][l[0]] + x * q, id = 0;
if(l[1] <= r[1] && Q[1][l[1]] + (x - l[1]) * q > max) max = Q[1][l[1]] + (x - l[1]) * q, id = 1;
if(l[2] <= r[2] && Q[2][l[2]] + (x - l[2]) * q > max) max = Q[2][l[2]] + (x - l[2]) * q, id = 2;
l[id]++; y = 1ll * max * u / v; z = max - y; if(y < z) Swap(y, z); Q[1][r[1]++] = y; Q[2][r[2]++] = z;
if(!((x + 1) % t)) printf("%d ", max);
}
void del(int i) {
if(i) while(l[i] <= r[i]) a[++cnt] = Q[i][l[i]] + (m - l[i]) * q, l[i]++;
else while(l[i] <= r[i]) a[++cnt] = Q[i][l[i]] + m * q, l[i]++;
}
/*----------------------------------------函数*/
int main() {
File();
n = read(); m = read(); q = read(); u = read(); v = read(); t = read();
l[0] = r[0] = l[1] = r[1] = l[2] = r[2] = 1;
for(int i = 1; i <= n; i++) Q[0][i] = read(); r[0] = n;
std::sort(Q[0] + 1, Q[0] + 1 + n, cmp);
for(int i = 1; i <= m; i++) work(i - 1);
for(int i = 0; i <= 2; i++) del(i);
std::sort(a + 1, a + 1 + cnt, cmp); puts("");
for(int i = t; i <= m + n; i += t) printf("%d ", a[i]);
return 0;
}
(T3) 愤怒的小鸟
(n^2) 枚举点对 待定系数法直接解方程 把 (x) 相等的判出去 把解出来 (a > 0) 的判出去 对于算出来的每一条抛物线 再枚举每个点 将经过的所有点都压进去 然后 (dp)
状态: (f_S) 表示经过点集为 (S) 时所用抛物线条数
转移时外层枚举状态 内层尝试将一个点纳入经过的集合 转移考虑将多少个点同时纳入
代码:
/*
Time: 6.15
Worker: Blank_space
Source:
*/
/*--------------------------------------------*/
#include<cstdio>
#include<cstring>
#define Abs(x) ((x) < 0 ? -(x) : (x))
#define Min(x, y) ((x) < (y) ? (x) : (y))
#define emm(x, a) memset(x, a, sizeof x)
/*--------------------------------------头文件*/
const double eps = 1e-9;
/*------------------------------------常量定义*/
inline void File() {
freopen("angrybirds.in", "r", stdin);
freopen("angrybirds.out", "w", stdout);
}
/*----------------------------------------文件*/
int T, n, m, cnt, s[20][20], f[(1 << 18) + 2], ans;
double x[20], y[20];
/*------------------------------------变量定义*/
inline int read() {
int x = 0, f = 1; char ch = getchar();
while(ch < '0' || ch > '9') {if(ch == '-') f = -1; ch = getchar();}
while(ch >= '0' && ch <= '9') {x = (x << 3) + (x << 1) + (ch ^ 48); ch = getchar();}
return x * f;
}
/*----------------------------------------快读*/
void work() {
n = read(); m = read(); emm(f, 63); emm(s, 0); f[0] = 0;
for(int i = 1; i <= n; i++) scanf("%lf%lf", x + i, y + i);
for(int i = 1; i < n; i++) for(int j = i + 1; j <= n; j++)
{
if(Abs(x[i] - x[j]) < eps) continue;
double a = (y[i] / (x[i] * x[i] - x[i] * x[j]) - y[j] / (x[i] * x[j] - x[j] * x[j]));
double b = (y[i] * x[j] * x[j] - y[j] * x[i] * x[i]) / (x[i] * x[j] * x[j] - x[j] * x[i] * x[i]);
if(a >= 0 || Abs(a) < eps) continue;
for(int k = 1; k <= n; k++) if(Abs(a * x[k] * x[k] + b * x[k] - y[k]) < eps) s[i][j] |= 1 << k - 1;
}
for(int S = 0; S < 1 << n; S++) for(int i = 1; i <= n; i++) if(!(1 << i - 1 & S))
{
for(int j = i; j <= n; j++)
{
if(i == j) f[S | (1 << i - 1)] = Min(f[S | (1 << i - 1)], f[S] + 1);
if(Abs(x[i] - x[j]) < eps) continue;
f[S | s[i][j]] = Min(f[S | s[i][j]], f[S] + 1);
}
break;
}
printf("%d
", f[(1 << n) - 1]);
}
/*----------------------------------------函数*/
int main() {
// File();
T = read(); while(T--) work();
return 0;
}