2016ccpc杭州

2016ccpc杭州

HDU 5933

题目要求

给出n个数字的大小 问能否通过某种操作变成大小全部相等的k堆
有两种操作:把相邻的两堆合并 把一堆拆成两堆
问最小的操作次数 无解输出-1

参考AC代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
#include<bits/stdc++.h>
#define maxn 100050
#define LL long long
using namespace std;
deque<LL>q;
int t,n,k;
int Case=1;
int main(){
// freopen("input.txt","r",stdin);
scanf("%d",&t);
while(t--){
scanf("%d%d",&n,&k);
q.clear();
LL sum=0;
for(int i=1;i<=n;i++){
LL x;
scanf("%d",&x);
sum+=x;
q.push_back(x);
}
printf("Case #%d: ",Case++);
if(sum%k!=0){
puts("-1");
continue;
}
LL temp=sum/k;
int ans=0;
while(!q.empty()){
LL x=q.front();
q.pop_front();
if(x==temp) continue;
else if(x>temp){
q.push_front(x-temp);
ans++;
}
else if(x<temp){
while(!q.empty()){
LL y=q.front();
q.pop_front();
ans++;
x+=y;
if(x>=temp){
q.push_front(x);
break;
}
}
}
}
printf("%d\n",ans);
}
return 0;
}

思路

双端队列模拟(普通队列也可以 答案跟合并顺序无关)
若大于平均数temp 拆成temp和x-temp
若小于temp 向后合并直到大于temp 再次执行上一次操作

HDU 5934

转跳链接

HDU 5935

题目要求

一辆车 从t=0开始走 速度只能递增 可为小数 警察在t为整数的时候记录了N个车的位置(整数) 问到达最后一个位置时最少开了多久

参考AC代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include<bits/stdc++.h>
#define maxn 100050
#define LL long long
using namespace std;
int t,n;
LL a[maxn];
int Case=1;
int main(){
// freopen("input.txt","r",stdin);
scanf("%d",&t);
while(t--){
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%lld",&a[i]);
LL fenzi=a[n]-a[n-1],fenmu=1;
LL time=1;
for(int i=n-1;i>=1;i--){
LL d=a[i]-a[i-1];
fenmu*=d;
LL tmp=fenmu/fenzi;
if(fenmu%fenzi!=0) tmp++;
time+=tmp;
fenzi=d;
fenmu=tmp;
}
printf("Case #%d: %lld\n",Case++,time);
}
return 0;
}

思路

贪心模拟
这题会卡精度
用分子分母模拟
先除再乘会损失精度 所以我们先乘再除

HDU 5938

题目要求

给出长度为20的字符串 每个位置为1-9
现在我们把他分成5段 四个间隔上依次加上+-×/四种符号 问能获得的最大数字是多少

参考AC代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#include<bits/stdc++.h>
#define LL long long
using namespace std;
const LL inf=(LL)1e18;
int t,Case=1;
char s[30];
int main(){
// freopen("input.txt","r",stdin);
scanf("%d",&t);
while(t--){
scanf("%s",s+1);
int len=strlen(s+1);
LL ans=-inf;
for(int i=1;i<=len-4;i++){
LL a=0;
for(int j=1;j<=i;j++) a=a*10*1LL+(s[j]-'0')*1LL;
for(int j=i+1;j<=len-3;j++){
LL b=0,c=0,d=0,e=0;
for(int k=i+1;k<=j;k++) b=b*10*1LL+(s[k]-'0')*1LL;
c=s[j+1]-'0';
d=s[j+2]-'0';
for(int k=j+3;k<=len;k++) e=e*10*1LL+(s[k]-'0')*1LL;
ans=max(ans,a+b-c*d/e);
}
}
printf("Case #%d: %lld\n",Case++,ans);
}
return 0;
}

思路

贪心模拟
要使减号后面的数字尽可能小 所以c和d只取一位 剩下的自然是e 所以只需n²枚举加号和减号即可
注意答案可能为负数 ans初始化为-inf 以及会爆int
注意b初始化的位置

文章目录
  1. 1. 2016ccpc杭州
    1. 1.1. HDU 5933
      1. 1.1.1. 题目要求
      2. 1.1.2. 参考AC代码
      3. 1.1.3. 思路
    2. 1.2. HDU 5934
    3. 1.3. HDU 5935
      1. 1.3.1. 题目要求
      2. 1.3.2. 参考AC代码
      3. 1.3.3. 思路
    4. 1.4. HDU 5938
      1. 1.4.1. 题目要求
      2. 1.4.2. 参考AC代码
      3. 1.4.3. 思路
|