qtmd AK了

直接题解吧

题目链接

A-十七边形

牛牛想在一个半径为r的圆中,找到一个内接的十七边形,使他的面积最大。输入半径r,输出最大的面积。 1 <= r <= 10000

在10组数据中,存在5组数据,半径为1,10,100,1000,10000。 换句话说,对于50%的数据,r是10的次幂。

输出保留6位小数

Solution:肯定是正十七边形喽

xjb证下:内接的十七边形一定把圆心角分为17份

那么根据叉积算面积,\(\displaystyle S=\frac {r^2} 2 \sum_{i=1}^{17}\sin(\theta_i)\),然后不会证了,反正十七个\(\theta\)相等一定是坠吼的

#include <bits/stdc++.h>
using namespace std; int r; int main()
{
scanf("%d", &r);
double fk = acos(-1) * 2 / 17.0;
double area = r * r * sin(fk);
area = area / 2.0 * 17;
printf("%f\n", area);
return 0;
}

B-首都

在平面上有n个整点(横纵坐标都是整数) 牛牛想找到一个整点,使得这个点,到所有点的距离之和最小。 两个点的距离定义为从一个点走到另一个点的最小步数。 其中每步可以走向相邻8个点(上,下,左,右,左上,左下,右上,右下,类似国际象棋中的王)走一步。 输出这个最小的距离之和,和这个点选择的方案数。(即有多少个点,可以达到这个最小的距离)

对于100%的数据,1 <= n <= 100000,|x|, |y| <= 1000000000 对于40%的数据,1 <= n <= 100,|x|, |y| <= 100 对于以上每部分数据,都有50%的数据n是奇数。

Sol:将坐标系顺时针旋转45度再放大一个\(\sqrt2\),根据线性变换理论,\((x,y)\rightarrow(x+y,x-y)\)

这样切比雪夫距离变味了曼哈顿距离,然后根据中位数定理求解

需要分各种情况讨论

N是奇数,根据中位数定理,只有一个点是最小值。但是,但是,这个点可能不合法。。。我们再逆变换变换回去,求\(A=\begin{pmatrix}1&1\\1&-1\end{pmatrix}\)的逆矩阵。行列式\(\det\begin{vmatrix}1&1\\1&-1\end{vmatrix}=-2\),伴随矩阵\(A^*=\begin{pmatrix}-1&1\\1&1\end{pmatrix}\),逆矩阵为\(\begin{pmatrix}\frac 1 2&-\frac 1 2\\-\frac 1 2&-\frac 1 2\end{pmatrix}\),显然我们需要两个数的奇偶性相同才行。不会用线性代数利器--矩阵推的同学可以画图观察,很显然的结论。

对于N是奇数,检验中间点坐标是否合格,如果合格那就是他了,直接暴力算结果。如果不合格,我们上下左右四个点坐标一定合格(可以自己画图看看),算那四个点坐标,找最小的输出就行了。

对于N是偶数,那么根据中位数定理,最小值是一段二维的区间。如果这个二维的区间缩成了一个点,用上面的思路处理就行了。否则这个区间一定包含合法的点。而且这个区间内的值是相同的,统计合法的点的数目,直接输出就行了。具体实现可以看代码。

#include <bits/stdc++.h>
using namespace std; int n;
long long x[100010], y[100010]; //最优解在一个点,如果那个点不合法,找他四个相邻的点 long long calc(long long xx, long long yy)
{
long long res = 0;
for (int i = 1; i <= n; i++)
res += abs(x[i] - xx) + abs(y[i] - yy);
return res;
} //偶数
long long calc_even(long long l, long long r)
{
long long len = (r - l + 1);
if (len % 2 == 0)
return len / 2;
else
{
if ((l & 1) && (r & 1))
return len / 2;
else
return len / 2 + 1;
}
} //奇数
long long calc_odd(long long l, long long r)
{
long long len = (r - l + 1);
if (len % 2 == 0)
return len / 2;
else
{
if ((l & 1) && (r & 1))
return len / 2 + 1;
else
return len / 2;
}
} void work1()
{
int mx = x[(n + 1) / 2], my = y[(n + 1) / 2];
if ((mx + my) & 1)
{
long long res[4];
res[0] = calc(mx - 1, my);
res[1] = calc(mx + 1, my);
res[2] = calc(mx, my - 1);
res[3] = calc(mx, my + 1);
sort(res, res + 4);
cout << res[0] / 2 << endl;
int t = 1;
if (res[0] == res[1])
{
t++;
if (res[1] == res[2])
{
t++;
if (res[2] == res[3])
{
t++;
}
}
}
cout << t << endl;
}
else
{
long long res = calc(mx, my);
cout << res / 2 << endl << 1 << endl;
}
} void work0()
{
long long x1 = x[n / 2], x2 = x[n / 2 + 1];
long long y1 = y[n / 2], y2 = y[n / 2 + 1];
//如果[x1, x2]或[y1, y2]区间长度大于1就钦定了
//当[x1, x2]和[y1, y2]都是一个点
//才用想上面那样特盘
if (x1 == x2 && y1 == y2)
{
if ((x1 + y1) & 1)
{
long long res[4];
res[0] = calc(x1 - 1, y1);
res[1] = calc(x1 + 1, y1);
res[2] = calc(x1, y1 - 1);
res[3] = calc(x1, y1 + 1);
sort(res, res + 4);
cout << res[0] / 2 << endl;
int t = 1;
if (res[0] == res[1])
{
t++;
if (res[1] == res[2])
{
t++;
if (res[2] == res[3])
{
t++;
}
}
}
cout << t << endl;
}
else
{
long long res = calc(x1, y1);
cout << res / 2 << endl << 1 << endl;
}
}
else
{
//否则这个二维区间内一定存在至少一个合法数字。
//现在任务是给定[x1, x2]和[y1, y2]求有多少合法数字。
//对于一个合法数字,一定是两个偶数或者两个奇数组成。
//所以只需要统计闭区间奇数和偶数的个数。
long long evenx = calc_even(x1, x2);
long long oddx = calc_odd(x1, x2);
long long eveny = calc_even(y1, y2);
long long oddy = calc_odd(y1, y2);
long long res = evenx * eveny + oddx * oddy;
long long ans = calc(x1, y1);
cout << ans / 2 << endl << res << endl;
}
} int main()
{
scanf("%d", &n);
for (int xx, yy, i = 1; i <= n; i++)
{
scanf("%d%d", &xx, &yy);
x[i] = xx + yy;
y[i] = xx - yy;
}
sort(x + 1, x + 1 + n);
sort(y + 1, y + 1 + n);
if (n & 1)
work1();
else
work0();
return 0;
}

C-分则能成

牛牛刚开始有一个正整数n。每次操作牛牛可以选择一个自己有的数字x,把x分为两正整数y和z,需满足x=y+z,然后获得y*z的收益。 (当然,在这个过程中,牛牛会失去x这个数字,并且获得y和z这2个数字。)

牛牛一共可以分k次,牛牛希望最大化这k次的收益之和。 因为分割的结果y和z是正整数,所以选择的x必须>=2。

对于100%的数据,1 <= k < n <= 109 对于40%的数据,1 <= k < n <= 10 对于70%的数据,1 <= k < n <= 100

Solution:(upd:所有的k改成了k+1)

打表发现,我们把N拆成k+1个均匀的数,xjb合并即可。

这些数的平均数是\(\displaystyle \frac N {k+1}\)(废话)

如果那个\(\displaystyle \frac N {k+1}\)是整数,那就是k+1个这数字喽。

如果\(\displaystyle \frac N {k+1}\)不是一个整数,那么

较小的数为\(\displaystyle \left\lfloor \frac N {k+1}\right\rfloor\),有\(\displaystyle {(k+1)}\left\lceil \frac N {k+1}\right\rceil-N\)个。

较大的数为\(\displaystyle \left\lceil\frac N {k+1}\right\rceil\),有\(\displaystyle N-{(k+1)}\left\lfloor\frac N {k+1}\right\rfloor\)个。(by GMPotlc: 这tmd就是\(N\mod(k+1)\)啊,你个sb)

同理,xjb合并即可。

合并的计算可以用分治,log级别。

全程开long long

#include <bits/stdc++.h>
using namespace std; //合并k个x得到的exp
//分治。。。log级别的
long long merge(long long x, long long k)
{
//一个合并个毛线
if (k == 1)
return 0;
if (k & 1)//k/2, k/2, 1
{
long long res = merge(x, k / 2);
long long yg = x * (k / 2);
return res * 2 + yg * yg + 2 * yg * x;
}
else
{
//k/2, k/2
long long res = merge(x, k / 2);
long long yg = x * (k / 2);
return res * 2 + yg * yg;
}
} int main()
{
long long n, k;
cin >> n >> k;
k++;
if (n % k == 0)
{
long long fuck = n / k;
cout << merge(fuck, k) << endl;
}
else
{
long long fuck1 = n / k, fuck2 = fuck1 + 1;
//向下取整,向上取整
long long t1 = k * fuck2 - n, t2 = n - k * fuck1;
long long res1 = merge(fuck1, t1);
long long res2 = merge(fuck2, t2);
long long tot1 = t1 * fuck1, tot2 = t2 * fuck2;
long long res3 = tot1 * tot2;
cout << res1 + res2 + res3 << endl;
}
return 0;
}

upd:dp打表程序,加一个#define csv就行

#include <bits/stdc++.h>
using namespace std; int f[110][110]; int main()
{
int n, k;
scanf("%d%d", &n, &k);
for (int x = 2; x <= n; x++)
for (int y = 1; y <= k; y++)
{
for (int i = 1; i < x; i++)//i, x - i
for (int j = 0; j < y; j++)//j, y - j - 1
f[x][y] = max(f[x][y], f[i][j] + f[x - i][y - j - 1] + i * (x - i));
}
printf("%d\n", f[n][k]);
#ifdef csv
freopen("data.csv", "w", stdout);
printf("he,");
for (int i = 0; i <= 100; i++)
printf("[%d],", i);
printf("\n");
for (int i = 0; i <= 100; i++)
{
printf("-%d-,", i);
for (int j = 0; j <= 100; j++)
printf("%d,", f[i][j]);
printf("\n");
}
#endif
return 0;
}

D-戴德兰

改了题面就是水题了

#include <bits/stdc++.h>
using namespace std; int n, c, d, a[10010]; int main()
{
scanf("%d%d%d", &n, &c, &d);
c += d;
for (int i = 1; i <= n; i++)
scanf("%d", &a[i]);
sort(a + 1, a + 1 + n);
for (int i = 1; i <= n; i++)
{
if (c - a[i] < 0)
{
printf("%d\n", i - 1);
break;
}
c -= a[i];
}
return 0;
}

牛客nowcoder NOIP普及组第三场的更多相关文章

  1. 牛客nowcoder Noip提高组第四场

    https://www.nowcoder.com/acm/contest/175#question A-动态点分治 Description CJK 是一个喜欢数据结构的同学.一天他看到 BZOJ 40 ...

  2. 牛客网多校训练第三场 C - Shuffle Cards(Splay / rope)

    链接: https://www.nowcoder.com/acm/contest/141/C 题意: 给出一个n个元素的序列(1,2,...,n)和m个操作(1≤n,m≤1e5),每个操作给出两个数p ...

  3. 牛客网多校训练第三场 A - PACM Team(01背包变形 + 记录方案)

    链接: https://www.nowcoder.com/acm/contest/141/A 题意: 有n(1≤n≤36)个物品,每个物品有四种代价pi,ai,ci,mi,价值为gi(0≤pi,ai, ...

  4. 2019牛客暑期多校训练营(第三场)- F Planting Trees

    题目链接:https://ac.nowcoder.com/acm/contest/883/F 题意:给定n×n的矩阵,求最大子矩阵使得子矩阵中最大值和最小值的差值<=M. 思路:先看数据大小,注 ...

  5. 牛客网2018暑期训练 第三场 a题

    #include <bits/stdc++.h> using namespace std; vector<int> path; ; short dp[maxn][maxn][m ...

  6. 2019牛客暑期多校训练营(第三场)H题目

    题意:给你一个N×N的矩阵,求最大的子矩阵 满足子矩阵中最大值和最小值之差小于等于m. 思路:这题是求满足条件的最大子矩阵,毫无疑问要遍历所有矩阵,并判断矩阵是某满足这个条件,那么我们大致只要解决两个 ...

  7. 2019牛客暑期多校训练营(第三场) F.Planting Trees(单调队列)

    题意:给你一个n*n的高度矩阵 要你找到里面最大的矩阵且最大的高度差不能超过m 思路:我们首先枚举上下右边界,然后我们可以用单调队列维护一个最左的边界 然后计算最大值 时间复杂度为O(n*n*n) # ...

  8. 牛客网NOIP赛前集训营-普及组(第二场)和 牛客网NOIP赛前集训营-提高组(第二场)解题报告

    目录 牛客网NOIP赛前集训营-普及组(第二场) A 你好诶加币 B 最后一次 C 选择颜色 D 合法括号序列 牛客网NOIP赛前集训营-提高组(第二场) A 方差 B 分糖果 C 集合划分 牛客网N ...

  9. 牛客网NOIP赛前集训营-提高组(第四场)游记

    牛客网NOIP赛前集训营-提高组(第四场)游记 动态点分治 题目大意: \(T(t\le10000)\)组询问,求\([l,r]\)中\(k(l,r,k<2^{63})\)的非负整数次幂的数的个 ...

随机推荐

  1. mybatis 学习五 动态SQL语句

    3.1 selectKey 标签 在insert语句中,在Oracle经常使用序列.在MySQL中使用函数来自动生成插入表的主键,而且需要方法能返回这个生成主键.使用myBatis的selectKey ...

  2. javascript——对象的概念——函数 2 (内建函数与类型转换)

    javascript 有许多内建函数,用于各种操作,以下为常用的内建方法. 1.parseInt(object,int):将输入的 int 进制的值 object 转换为 10 进制的数值: obje ...

  3. 用JS,求斐波那契数列第n项的值

    <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title&g ...

  4. VI中的多行删除与复制(转)

    VI中的多行删除与复制 法一: 单行删除,:(待删除行)d 多行删除 ,:,10d 法二: 光标所在行,dd 光标所在行以下的N行,Ndd 方法1: 光标放到第6行, 输入:2yy 光标放到第9行, ...

  5. matlab图片高清复制到visio

    编辑→复制图窗→在visio中粘贴

  6. 2-2 zookeeper下载、安装以及配置环境变量

    https://archive.apache.org/dist/zookeeper/zookeeper-3.4.11/ FTP的软件:FileZilla Client 登录腾讯云服务器tail /va ...

  7. POJ 1741 点分治

    方法:指针扫描数组 每次选择树的重心作为树根,从树根出发进行一次DFS,求出点到树根的距离,把节点按照与树根的的距离放进数组d,设置两个指针L,R分别从前.后开始扫描,每次满足条件时答案累加R-L., ...

  8. HDU 6395(2018多校第7场1010)Sequence

    不久前做过POJ3070,所以知道这题要用矩阵快速幂优化,但是这个题的递推公式中有一项⌊p/n⌋,场上就不会了... 下来才知道要用分块矩阵快速幂,因为⌊p/n⌋最多有2√p块,可以对每一块使用快速幂 ...

  9. Python Matplotlib.plot Update image Questions

    1. 最近在测试一款设备,采集了一些设备后需要一帧一帧显示图像,经常使用Python,所以选用了Matplotlib进行图像操作 数据结构: timesatamp polar_distance hor ...

  10. p3253 [JLOI2013]删除物品

    传送门 分析 我们发现两个栈可以看作一个数组,而栈顶则是将这个数组拆成两个栈的分割点. 于是每次移动就变成了分割点的移动,每次移动时都统计下目的分割点和当前分割点之间的物品数目即可. 代码 #incl ...