多测不清空,爆零两行泪。
A - Energy Crystals
题意
有三个整数 a 1 a_1 a1, a 2 a_2 a2, a 3 a_3 a3,可以将其中一个数改为任意正整数,但是必须满足对于任意两个 i i i, j ( 1 ≤ i , j ≤ 3 ) j(1\le i,j\le3) j(1≤i,j≤3),有:
a i ≥ ⌊ a j 2 ⌋ a_i\ge\lfloor\frac{a_j}{2}\rfloor ai≥⌊2aj⌋
求对这三个数最少操作多少次使得三个数都变成 n n n
分析
先来枚举一下对于第 i i i次操作最大能达到多少。
i | max |
---|---|
1 | 1 |
2 | 1 |
3 | 3 |
⋯ \cdots ⋯ | ⋯ \cdots ⋯ |
2 n 2n 2n | 2 n − 1 2^{n}-1 2n−1 |
2 n + 1 2n+1 2n+1 | 2 n − 1 2^{n}-1 2n−1 |
(后面两组找规律可得)
对于两个整数 a a a和 b b b,且 a < b a<b a<b,如果在第 i i i次可以达到 b b b,那么也能达到 a a a。
所以,思路就是找一个正整数 p p p,使得 2 p − 1 ≤ n 2^p-1\le n 2p−1≤n,最后的答案就是 2 n + 1 2n+1 2n+1
#include<bits/stdc++.h>
#define int long long
#define endl putchar('\n')
using namespace std;
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-'0',c=getchar();
return x*f;
}
void print(int x){
if(x<0)putchar('-'),x=-x;
if(x<10){putchar(x+'0');return;}
print(x/10);
putchar(x%10+'0');
}
int T;
signed main(){
T=read();
while(T--){
int x=read();
int ans=1,i;
for(i=1;i<=64;i++){
ans=ans*2;
if(ans>x)break;
}
print(i*2+1);
endl;
}
}
B - Fibonacci Cubes
题意
有 n n n个正方体,第 i i i个正方体的棱长为 f i f_i fi,对于 f i f_i fi,有:
f 1 = 1 f 2 = 2 f i = f i − 1 + f i − 2 ( f > 2 ) f_1=1\\ f_2=2\\ f_i=f_{i-1}+f_{i-2}(f>2) f1=1f2=2fi=fi−1+fi−2(f>2)
有 m m m个盒子,第 i i i个盒子的长宽高分别为 w i w_i wi, h i h_i hi, l i l_i li。
立方体摆放需遵循以下规则:
- 立方体必须与盒子边平行放置;
- 每个立方体必须直接放置在盒底,或叠放在其他立方体上且下方空间必须被完全填满;
- 较大的立方体不能叠放在较小立方体上。
问这些盒子分别能不能按要求装下所有正方体。
分析
由于 n n n个盒子的棱长分别是斐波拉切数列的前 n n n位,所以可以考虑下图:(正方形表示正方体的俯视图,正方形内数字表示正方体的棱长)。
可以发现,对于第 n n n个正方体,只要其上还剩下 f n − 1 f_{n-1} fn−1高度的盒子空间,那么就能放下第 n − 1 n-1 n−1个正方体,对于第 n − 1 n-1 n−1个正方体以此类推……
最后可以证明,只要能放下第 n n n个和第 n − 1 n-1 n−1个正方体,就能放下所有的正方体。
#include<bits/stdc++.h>
#define endl putchar('\n')
using namespace std;
const int N=1e6+5;
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-'0',c=getchar();
return x*f;
}
void putstr(string s){
for(int i=0;i<s.size();i++)putchar(s[i]);
}
int n,m;
int T;
int w[N],h[N],l[N];
int f[N]={1,1};
signed main(){
T=read();
for(int i=2;i<=10;i++)f[i]=f[i-1]+f[i-2];
while(T--){
n=read(),m=read();
for(int i=1;i<=m;i++)w[i]=read(),h[i]=read(),l[i]=read();
string p="";
for(int i=1;i<=m;i++){
if(f[n]>w[i]||f[n]>h[i]||f[n]>l[i]){//检查第n个正方体
p.push_back('0');
continue;
}
int x=w[i]-f[n],y=h[i]-f[n],z=l[i]-f[n];
if(f[n-1]>x&&f[n-1]>y&&f[n-1]>z){//检查第n-1个正方体
p.push_back('0');
continue;
}
p.push_back('1');
}
putstr(p);
endl;
}
}
C - Equal Values
题意
有 n n n个整数 a 1 a_1 a1, a 2 a_2 a2, a 3 … a n a_3\ldots a_n a3…an,可以进行两种操作:
- 选择位置 i i i,将 a 1 … i − 1 a_{1\ldots i-1} a1…i−1全部变成 a i a_i ai,代价为 ( i − 1 ) ⋅ a i (i-1)\cdot a_i (i−1)⋅ai
- 选择位置 i i i,将 a i + 1 … n a_{i+1\ldots n} ai+1…n全部变成 a i a_i ai,代价为 ( n − i ) ⋅ a i (n-i)\cdot a_i (n−i)⋅ai
求将 n n n个整数全部变成一样的最小代价。
分析
举例两个情况
情况1
5 2 2 5 2 2 5\\2\ 2\ 5\ 2\ 2 52 2 5 2 2
这个时候选择 a 2 a_2 a2向右边变化,代价为 6 6 6,虽然说右边只有 5 5 5这个不同的数字,但是还是得将 5 2 2 5\ 2\ 2 5 2 2三个数全部变化。
可以得出,当两部分相同的数没有相连的时候,互相没有任何影响。
情况2
8 5 4 2 2 2 2 2 1 8\\5\ 4\ 2\ 2\ 2\ 2\ 2\ 1 85 4 2 2 2 2 2 1
有一种方案是选择 a 8 a_8 a8向左边变化,代价为 7 7 7,但明显不是最优的。可选择 a 3 a_3 a3向左变化 a 7 a_7 a7向右变化,代价为 6 6 6,中间由于都是 2 2 2就不用变了。
可以得出,对于相邻数,互相是有影响的,变化时只用取两端的数左右变化就行了。
可以先求出每一个点对应联通块的左右端点,然后记录最小值就行了。
#include<bits/stdc++.h>
#define int long long
#define endl putchar('\n')
using namespace std;
const int N=1e6+5;
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-'0',c=getchar();
return x*f;
}
void print(int x){
if(x<0)putchar('-'),x=-x;
if(x<10){putchar(x+'0');return;}
print(x/10);
putchar(x%10+'0');
}
int n;
int T;
int a[N];
int f[N];
int k[N];
signed main(){
T=read();
while(T--){
n=read();
for(int i=1;i<=n;i++)a[i]=read(),f[i]=i,k[i]=i;
for(int i=2;i<=n;i++){
if(a[i]==a[i-1])f[i]=f[i-1];
}
for(int i=n-1;i>=1;i--){
if(a[i]==a[i+1])k[i]=k[i+1];
}
int mn=1e18;
for(int i=1;i<=n;i++){
mn=min(mn,(f[i]-1)*a[i]+(n-k[i])*a[i]);
}
print(mn);
endl;
}
}
D - Creating a Schedule
题意
有 n n n个班级和 m m m间教室,教室编号为一个至少三位的数,出去最后两位剩下的表示教室所在的楼层。
这 n n n个班级每天都有 6 6 6节课,且每个班级的第 k k k节课在同一时间进行,两个班级不能同时在同一件教室上课。
请你设计一个课程表,使每个班级学生上下楼移动的距离最大。
分析
先考虑两个班级的情况。
当只有两个班级的时候,可以考虑让两个班级在最高层的最底层之间交替上课,可以实现移动最大化。
当出现第三个班级的时候,可以考虑让其在次大层和次小层移动,获得最大收益。
第四层同理。
以此类推。