长乐培训Day3
T1 奶牛晒衣服
题目
【题目描述】
在熊大妈英明的带领下,时针和他的同伴生下了许多牛宝宝。熊大妈决定给每个宝宝都穿上可爱的婴儿装。于是,为牛宝宝洗晒衣服就成了很不爽的事情。
圣人王担负起了这个重任。洗完衣服后,你就要弄干衣服。衣服在自然条件下用1的时间可以晒干A点湿度。抠门的熊大妈买了1台烘衣机。
使用烘衣机可以让你用1的时间使1件衣服除开自然晒干的A点湿度外,还可烘干B点湿度,但在1的时间内只能对1件衣服使用。
N件的衣服因为种种原因而不一样湿,现在告诉你每件衣服的湿度,要你求出弄干所有衣服的最少时间(湿度为0为干)。
【输入格式】
第一行N,A,B,接下来N行,每行一个数,表示衣服的湿度。
【输出格式】
一行,最少时间。
【输入样例】
3 2 1
1
2
3
【输出样例】
1
【数据规模】
1<=湿度,A,B<=500000,1<=N<=500000。
解析
第一题依旧是送分的(安慰一下其他题爆零的情绪QAQ)。
直接二分即可,每次循环中只需要判断s[i](湿度)与a*mid(mid为天数)的大小就可以了。
最后的答案即为l。
Code
#include <algorithm>
#include <iostream>
#include <cstring>
#include <string>
#include <cstdio>
#include <cmath>
using namespace std;
int read()
{
int num=,w=;
char ch=getchar();
while(ch<''||ch>'')
{
if(ch=='-') w=-;
ch=getchar();
}
while(ch>=''&&ch<='')
{
num=(num<<)+(num<<)+ch-'';
ch=getchar();
}
return num*w;
}
int n,a,b,s[];
long long l,r,mid;
bool cmp(int x,int y)
{
return x>y;
}
int main()
{
//freopen("dry.in","r",stdin);
//freopen("dry.out","w",stdout);
n=read(),a=read(),b=read();
for(int i=;i<=n;i++)
{
s[i]+=read();
r+=s[i];
}
while(l<=r)
{
long long ans=;
mid=(l+r)>>;
for(int i=;i<=n;i++)
if(s[i]-a*mid>)
{
if((s[i]-a*mid)%b==) ans+=(s[i]-a*mid)/b;
else ans+=(s[i]-a*mid)/b+;
}
if(ans<=mid) r=mid-;
else l=mid+;
}
cout<<l;
return ;
//fclose(stdin);
//fclose(stdout);
}
T2 解密文件
题目
【题目描述】
已知英语中26个字母出现的概率p[0],p[1]……,p[25](它们的和为1),分别表示’a’, ‘b’,‘c’……出现的概率(大写字母和小写字母被认为是一样的)。
现在有一个加密过的文件,加密方法是将原文件中的每一个字母进行相同的变换,其他的字符不变,变换的方法如下:
如果将a到z编号为0到25,那么字母i将被替换成(i+k) mod 26,0<=k<26。原来是大写的字母,仍然是大写,原来是小写的字母仍然是小写。
但是你并不知道k的值,所以只好枚举。因为知道26个字母出现的频率,所以你可以选择一个尽量好的k,使得频率的方差和最小,方差和定义如下:
假设你枚举的k还原出来的原文件中的26个字母出现的概率为x[0], x[1], ……, x[25],那么方差和为:(p[0]-x[0])^2 + (p[1]-x[1])^2 + …… + (p[25]-x[25])^2。
如果有两个相同的k一样好,那么选较小的k。
最后输出解密出的原文件。
【输入格式】
前26行分别是26个字母出现的概率。
接下来是一个只含有26个大小写字母和空格,换行符,标点符号,阿拉伯数字等的文本。
【输出格式】
解密过的文本。
【输入样例】
0.109375
0.000000
0.062500
0.015625
0.109375
0.015625
0.015625
0.000000
0.062500
0.015625
0.000000
0.078125
0.062500
0.062500
0.093750
0.015625
0.015625
0.031250
0.046875
0.046875
0.046875
0.000000
0.000000
0.000000
0.093750
0.000000
L dp Ol Bxtldq, ru brx fdq fdoo ph VsdfhIobhu.
L dp jodg wr vhh brx.
Hqmrb pb frqwhvw.
【输出样例】
I am Li Yuqian, or you can call me SpaceFlyer.
I am glad to see you.
Enjoy my contest.
【数据规模】
输入文件不超过10k。
解析
这题直接模拟即可,非常恶心有趣。
先预处理出a数组(每个数字所对应的字母,0-25表示a-z,26-51表示A-Z)。
处理文本我用的是string,直接while循环getline(cin,s[++temp]),这里有两个细节:
1、输入时要先输入一个“\n”(我也不知道为什么,反正它会读入一个换行);
2、由于++temp,所以即使没有读入了还是会自加一次,所以要-1或者输出时把<=改成<。
关于每个字母的频率,本蒟蒻是在枚举k时每次都计算,实际上并不用那么麻烦,
因为每个字母都是由初始字母一一对应转换来的,所以只需要计算初始字母的频率就行了(输入时明明给了的说)。
然后取方差和最小的即可。输出时如果是字母要分大写和小写处理,
小写输出a[(int)((s[i][j]-'a'+kk)%26)],大写输出a[(int)((s[i][j]-'A'+kk)%26+26)](预处理a数组是大写字母实在小写字母基础上+26的)。
如果不是字母直接输出原来的文本就好了。
Code
#include <algorithm>
#include <iostream>
#include <cstring>
#include <string>
#include <cstdio>
#include <cmath>
using namespace std;
int temp=,sum[],kk;
double p[],x[],ans,minn=1000000.0;
char a[];
string s[];
int main()
{
//freopen("decode.in","r",stdin);
//freopen("decode.out","w",stdout);
for(int i=;i<;i++) a[i]=char('a'+i);
for(int i=;i<;i++) a[i]=char('A'+i-);
for(int i=;i<;i++) cin>>p[i];
scanf("\n");
while(getline(cin,s[++temp])) ;
for(int k=;k<;k++)
{
memset(sum,,sizeof(sum));
ans=0.0;
for(int i=;i<=temp;i++)
for(int j=;j<s[i].size();j++)
{
if(s[i][j]>='a'&&s[i][j]<='z') sum[(s[i][j]-'a'+k)%]++;
if(s[i][j]>='A'&&s[i][j]<='Z') sum[(s[i][j]-'A'+k)%]++;
}
for(int i=;i<;i++)
{
x[i]=(double)(sum[i]*0.03846153846);
ans+=(p[i]-x[i])*(p[i]-x[i]);
}
if(ans<minn)
{
minn=ans;
kk=k;
}
}
for(int i=;i<temp;i++)
{
for(int j=;j<s[i].size();j++)
{
if(s[i][j]>='a'&&s[i][j]<='z') cout<<a[(int)((s[i][j]-'a'+kk)%)];
else if(s[i][j]>='A'&&s[i][j]<='Z') cout<<a[(int)((s[i][j]-'A'+kk)%+)];
else cout<<s[i][j];
}
cout<<endl;
}
return ;
//fclose(stdin);
//fclose(stdout);
}
T3 休息
题目
【题目描述】
休息的时候,可以放松放松浑身的肌肉,打扫打扫卫生,感觉很舒服。在某一天,某LMZ开始整理他那书架。
已知他的书有n本,从左到右按顺序排列。他想把书从矮到高排好序,而每一本书都有一个独一无二的高度Hi。
他排序的方法是:每一次将所有的书划分为尽量少的连续部分,使得每一部分的书的高度都是单调下降,然后将其中所有不少于2本书的区间全部翻转。
重复执行以上操作,最后使得书的高度全部单调上升。可是毕竟是休息时间,LMZ不想花太多时间在给书排序这种事上面。
因此他划分并翻转完第一次书之后,他想计算,他一共执行了多少次翻转操作才能把所有的书排好序。
LMZ惊奇地发现,第一次排序之前,他第一次划分出来的所有区间的长度都是偶数。
【输入格式】
第一行一个正整数n, 为书的总数。
接下来n行,每行仅一个正整数Hi,为第i本书的高度。
【输出格式】
仅一个整数,为LMZ需要做的翻转操作的次数。
【输入样例】
6
5 3 2 1 6 4
【输出样例】
3
【数据规模】
对于10%的数据:n<=50
对于40%的数据:n<=3000
对于100%的数据:1<=n<=100000, 1<=Hi<=n
解析
其实这题就是在求逆序对,所以用归并排序来做。
在归并的过程中,如果a[i]>a[j],即逆序对,则ans+=mid-i+1,具体原因模拟一遍就知道了。
程序中运用到的reverse函数是<algorithm>里的,作用是翻转,在给p[cnt].r赋值的时候,赋的是i-1,所以在翻转时,得在最后+1。
答案是在n2/2的,很显然int是不够的,记得开long long。
Code
#include<algorithm>
#include<iostream>
#include<cstdio>
using namespace std;
const int N = 1e5 + ;
int c[N], a[N], n;
long long ans;
void msort(int l, int r) {
if(l == r) return;
int mid = (l + r) >> ;
msort(l, mid), msort(mid + , r);
int i = l, j = mid + , k = l;
while(i <= mid && j <= r) {
if(a[i] <= a[j])
c[k++] = a[i++];
else {
ans += mid - i + ;
c[k++] = a[j++];
}
}
while(i <= mid) c[k++] = a[i++];
while(j <= r) c[k++] = a[j++];
for(int t = l; t <= r; t++)
a[t] = c[t];
}
struct rec {
int l, r;
}p[N];
int main() {
//freopen("rest.in", "r", stdin);
//freopen("rest.out", "w", stdout);
int cnt = ;
scanf("%d", &n);
for(int i = ; i <= n; i++) {
scanf("%d", a + i);
if(a[i] > a[i - ]) {
p[cnt].r = i - ;
p[++cnt].l = i;
}
}
p[cnt].r = n;
for(int i = ; i <= cnt; i++)
reverse(a + p[i].l, a + p[i].r + ), ans++;
msort(, n);
cout<<ans;
return ;
}
T4 矩阵取数游戏
题目
【题目描述】
帅帅经常跟同学玩一个矩阵取数游戏:对于一个给定的n*m的矩阵,矩阵中的每个元素aij均为非负整数。游戏规则如下:
1.每次取数时须从每行各取走一个元素,共n个。m次后取完矩阵所有的元素;
2.每次取走的各个元素只能是该元素所在行的行首或行尾;
3.每次取数都一个得分值,为每行取数的得分之和;每行取数的得分=被取走的元素值*2i,其中i表示第i次取数(从1开始编号);
4.游戏结束总得分为m次取数得分之和。
帅帅想请你帮忙写一个程序,对于任意矩阵,可以求出取数后的最大得分。
【输入格式】
输入文件包括n+1行:
第一行为两个用空格隔开的整数n和m。
第2~n+1行为n*m矩阵,其中每行m个用单个空格隔开。
【输出格式】
输出文件仅包含1行,为一个整数,即输入矩阵取数后的最大的分。
【输入样例】
2 3
1 2 3
3 4 2
【输出样例】
82
【数据规模】
60%的数据满足:1<=n, m<=30,答案不超过1016
100%的数据满足:1<=n, m<=80,0<=aij<=1000
解析
这题实际上一眼就可以看出是区间DP。
令f[i][j]表示第k行取数取成了[i,j]的区间的得分。
由于只能从左右两端取,所以状态转移方程显而易见:
f[i][j]=max(f[i-1][j]+a[i-1][j]*2m-j+i-1,f[i][j+1]+a[i][j+1]*2m-j+i-1)
由于本蒟蒻的代码i和j都是从0开始循环的所以2的次方并不是m-j+i-1,而是i+j(个人更推荐上面的写法,更通俗易懂)。
好了,这题就是这样。
才怪,
如果单单只是这样的话,这题就太简单了,
但是!!!!!
注意看数据范围,m最大为80,那么2的80次方是多少?1208925819614629174706176!
这么大的数int不行,long long也不行,哪怕是unsigned long long也不够,那怎么办呢?
答案是:高精!
高精才是这道题真正恶心的地方,需要用到的有:
高精+高精、高精*单精、max(高精,高精)。
所以本蒟蒻来讲一下高精如何实现......才怪。
由于本蒟蒻不会高精,所以下面代码中的高精是直接从标程“借鉴”来的(手动滑稽)。
Code
#include <algorithm>
#include <iostream>
#include <cstring>
#include <string>
#include <cstdio>
#include <cmath>
using namespace std;
int read()
{
int num=,w=;
char ch=getchar();
while(ch<''||ch>'')
{
if(ch=='-') w=-;
ch=getchar();
}
while(ch>=''&&ch<='')
{
num=(num<<)+(num<<)+ch-'';
ch=getchar();
}
return num*w;
}
int n,m,a[][];
struct sb{
int c[];
friend inline sb operator * (const sb &a, const int &b)
{
sb c;
for(int i = ; i <= ; i ++)
c.c[i] = ;
c.c[] = a.c[];
int p = ;
for(int i = ; i <= a.c[]; i ++)
{
c.c[i] = a.c[i] * b + p;
p = c.c[i] / ;
c.c[i] %= ;
}
int &len = c.c[];
while (p)
{
c.c[++len] = p % ;
p /= ;
}
return c;
}
friend inline sb operator * (const sb &a, const sb &b)
{
sb c;
for(int i = ; i <= ; i ++)
c.c[i] = ;
c.c[] = a.c[] + b.c[] - ;
for(int i = ; i <= a.c[]; i ++)
{
int p = ;
for(int j = ; j <= b.c[]; j ++)
{
c.c[i + j - ] += a.c[i] * b.c[j] + p;
p = c.c[i + j - ] / ;
c.c[i + j - ] %= ;
}
c.c[i + b.c[]] += p;
}
if (c.c[c.c[] + ]) c.c[] ++;
return c;
}
friend inline sb operator + (const sb &a, const sb &b)
{
sb c;
int &len = c.c[];
c.c[] = max(a.c[], b.c[]);
for(int i = ; i <= ; i ++)
c.c[i] = ;
int p = ;
for(int i = ; i <= len; i ++)
{
c.c[i] = a.c[i] + b.c[i] + p;
p = c.c[i] / ;
c.c[i] %= ;
}
if (p) len ++, c.c[len] = p;
return c;
}
inline sb operator = (const sb &b)
{
c[] = b.c[];
for(int i = ; i <= ; i ++)
c[i] = ;
for(int i = ; i <= b.c[]; i ++)
c[i] = b.c[i];
return *this;
}
inline void print()
{
cout << c[c[]];
for(int i = c[] - ; i >= ; i --)
printf("%04d", c[i]);
cout << endl;
}
};
inline sb Max(const sb &a, const sb &b)
{
if (a.c[] > b.c[]) return a;
else if (a.c[] < b.c[]) return b;
else if (a.c[] == b.c[])
{
for(int i = a.c[]; i >= ; i --)
if (a.c[i] > b.c[i]) return a;
else if (a.c[i] < b.c[i]) return b;
}
return a;
}
sb f[][],cf[],tot,ans;
int main()
{
//freopen("game.in","r",stdin);
//freopen("game.out","w",stdout);
n=read(),m=read();
for(int i=;i<=n;i++)
for(int j=;j<=m;j++) a[i][j]=read();
cf[].c[]=;cf[].c[]=;
for(int i=;i<=m;i++) cf[i]=cf[i-]*;
for(int k=;k<=n;k++)
{
for(int i=;i<=m;i++)
for(int j=;j<=m;j++) memset(f[i][j].c,,sizeof(f[i][j].c));
f[m][m].c[]=;
memset(tot.c,,sizeof(tot.c));
tot.c[]=;
for(int i=;i<=m;i++)
for(int j=;j<=m-i;j++)
{
if(i==&&j==) continue;
if(i) f[i][j]=Max(f[i][j],f[i-][j]+cf[i+j]*a[k][i]);
if(j) f[i][j]=Max(f[i][j],f[i][j-]+cf[i+j]*a[k][m-j+]);
tot=Max(tot,f[i][j]);
}
ans=ans+tot;
}
ans.print();
//fclose(stdin);
//fclose(stdout);
return ;
}
长乐培训Day3的更多相关文章
- 纪中2018暑假培训day3提高a组改题记录(混有部分b组)
day3 模拟赛,看了看a组题,发现是博弈论,非常开心(因为好玩),于是做的a组.结果差点爆零,死命纠结t1的sg函数,但其实只是一个dp,不用扯到sg函数的那种. t1: Description 被 ...
- 常州培训 day3 解题报告
第一题: 给出数轴正半轴上N个点的坐标和其权值,给出初始体力值M,人一开始在位置0,体力值会随着走过路程的增加而增加,走多少个单位的路消耗多少体力值.到每个点可以打掉,消耗的体力值就是其权值.求 最多 ...
- 泉五培训Day3
T1 家庭作业 题目 [问题描述] 小P为了能高效完成作业,规定每项作业花一个单位时间. 他的学习日从0时刻开始,有100000个单位时间.在任一时刻,他都可以选择编号1~N的N项作业中的任意一项作业 ...
- 正睿暑期培训day3考试
链接 A 可以发现一个小棍的贡献是使得左右两列上的球位置互换.所以只要找出哪两个球会经过当前位置,然后swap一下就行了.. 考场上调了2.5h,依然没过样例.赛后发现忘了排序!!!!... /* * ...
- 长乐培训Day4
T1 矩阵 题目 [题目描述] 从前有个 n×m 的矩阵,初始时每个位置均为 0.你需要依次执行 q 个操作,每个操作会指定一行或一列,然后将该行或该列的所有元素全部赋为一个相同的值. 输出操作完成后 ...
- 长乐培训Day9
T1 立方数 题目 [题目描述] 作为XX战队的狂热粉丝,MdZzZZ看到了自己心仪的队伍在半决赛落败,顿时心灰意冷.看着自己手中的从黄牛那里抢来的天价总决赛门票,MdZzZZ觉得去鸟巢已经没有意义了 ...
- 长乐培训Day8
T1 远征 题目 [题目描述] 寒枫将军将要带领他的部队去圣雪山消灭那里的冰龙.部队分成了若干个小队,属于同一个小队的人兵种相同. 寒枫将军有着杰出的指挥能力,在战斗的时候,寒枫将军能够让所有相同兵种 ...
- 长乐培训Day7
T1 删除 题目 [题目描述] 现在,我的手上有 n 个数字,分别是 a1,a2,a3,...,an. 我现在需要删除其中的 k 个数字.当然我不希望随随便便删除,我希望删除 k 数字之后,剩下的 n ...
- 长乐培训Day6
T1 数列 题目 [题目描述] [输入格式] [输出格式] [输入样例] [输出样例] [数据规模] 如上所述. 解析 身为T1,居然比T4还难......让我怎么办......以下为巨佬题解: 我猜 ...
随机推荐
- Linux下DM无法显示建模界面的解决方法
方法来源: http://www.linuxhospital.com/read/unable-to-resolve-function-glxqueryextension-in-hyperview.ht ...
- Java多线程相关的API方法以及作用摘要
wait() 会让当前运行线程 阻塞,并释放对应的对象锁, 一般由当前线程持有的对象锁调用 x.wait(): 当前线程必须拥有此对象的monitor(即锁),才能调用此对象的wait()方法能让当前 ...
- Python_Openpyxl 浅谈(最全总结 足够初次使用)
https://blog.csdn.net/weixin_43094965/article/details/82226263 import datetime from random import ch ...
- layer.msg如何让按钮的回调执行完毕后弹框不自动关闭
问题出现:我点击“确定”时会验证“新手机号码”,如果验证不通过则不给该弹框关掉,但是实际操作时,不管验证怎么样,点击“确定”之后该弹框都会关掉. 之前的写法: layer.open({ ...
- linux中截取字段与#、$区别
1.Linux shell 截取字符变量的前8位 实现方法有如下几种: expr substr “$a” 1 8 echo $a|awk ‘{print substr(,1,8)}’ echo $a| ...
- [转]BigDecimal使用(整理)
原文地址:https://www.jianshu.com/p/2947868d76eb 应用场景 大多数的商业计算中,一般采用java.math.BigDecimal类来进行精确计算.比如:货币 使用 ...
- 真正的能理解CSS中的line-height,height与line-height
https://blog.csdn.net/a2013126370/article/details/82786681 在最近的项目中,常常用到line-height,只是简单的理解为行高但并没有深层次 ...
- vue模块化以及封装Storage组件实现保存搜索的历史记录
<template> <div id="app"> <input type="text" v-model='todo' @keyd ...
- 解决 service iptables save 报错 please try to use systemctl
本文档根据 service iptables save 报错 please try to use systemctl 提供解决方案.报错 [root@Jaking ~]# service iptabl ...
- windows nginx 快捷启动关闭批处理脚本
:: 关闭回显,即执行本脚本时不显示执行路径和命令,直接显示结果 @echo off rem @author luwuer color f8 set NGINX_DIR=D:\nginx-1.12.2 ...