A.日期统计
小蓝现在有一个长度为100 的数组,数组中的每个元素的值都在0 到9 的范围之内,现在他想要从这个数组中寻找一些满足以下条件的子序列,对于相同的日期你只需要统计一次即可。
暴力走一遍就可以了,就是麻烦了一点,毕竟新手。
#include<iostream>
#include<cstdio>
#include<bits/stdc++.h>
using namespace std;
int dayx[13]={0,31,28,31,30,31,30,31,31,30,31,30,31};
int main()
{
int p[42];
int res,ant=1,flog,flog1,flog2,flog4,flog3;
for(int i=1;i<=41;i++){
cin>>p[i];
}
for(int i=1;i<=12;i++){
for(int j=1;j<=dayx[i];j++){
ant=1;
flog1=flog2=flog3=flog4=0;
if(i<10){
for(int a=ant;a<=41;a++){
ant=a;
if(p[a]==0){
flog4=1;
break;
}
}
}else{
for(int a=ant+1;a<=41;a++){
ant=a;
if(i/10==p[a]){
flog4=1;
break;
}
}
}
for(int a=ant+1;a<=41;a++){
ant=a;
if(i%10==p[a]){
flog3=1;
break;
}
}
if(j<10){
for(int a=ant+1;a<=41;a++){
ant=a;
if(p[a]==0){
flog2=1;
break;
}
}
}else{
for(int a=ant+1;a<=41;a++){
ant=a;
if(j/10==p[a]){
flog2=1;
break;
}
}
}
for(int a=ant+1;a<=41;a++){
ant=a;
if(j%10==p[a]){
flog1=1;
break;
}
}
if(flog1&&flog2&&flog3&&flog4&&ant<=41){
res++;
cout<<i<<' '<<j<<endl;
}
}
}
cout<<res<<endl;
return 0;
}
B.01 串的熵
对于一个长度为 n 的 01 串 S = x1 x2 x3...xn,香农信息熵的定义为 H(S ) = −Σ n 1 p(xi)log2 (p(xi)),其中 p(0), p(1) 表示在这个 01 串中 0 和 1 出现的占比。 比如,对于 S = 100 来说,信息熵 H(S ) = − 1 3 log2 ( 1 3 ) − 2 3 log2( 2 3 ) − 2 3 log2 ( 2 3 ) = 1.3083。对于一个长度为 23333333 的 01 串,如果其信息熵为 11625907.5798, 且 0 出现次数比 1 少,那么这个 01 串中 0 出现了多少次?
需要double确定一下精度,然后带公式进去。
#include<iostream>
#include<cstdio>
#include<bits/stdc++.h>
using namespace std;
int n=23333333;
void check(int i){
int n=23333333;
double x=(-1.0)*i/n*log2(1.0*i/n)*i;
double y=(-1.0)*(n-i)/n*log2(1.0*(n-i)/n)*(n-i);
if(x+y>=11625907.5798 && x+y<=11625907.5799){
cout<<i;
return;
}
return ;
}
int main()
{
for(int i=1;i<=n/2;i++){
check(i);
}
return 0;
}
C.冶炼金属
小蓝有一个神奇的炉子用于将普通金属 O 冶炼成为一种特殊金属 X。这个 炉子有一个称作转换率的属性 V,V 是一个正整数,这意味着消耗 V 个普通金 属 O 恰好可以冶炼出一个特殊金属 X,当普通金属 O 的数目不足 V 时,无法 继续冶炼。 现在给出了 N 条冶炼记录,每条记录中包含两个整数 A 和 B,这表示本次 投入了 A 个普通金属 O,最终冶炼出了 B 个特殊金属 X。每条记录都是独立 的,这意味着上一次没消耗完的普通金属 O 不会累加到下一次的冶炼当中。 根据这 N 条冶炼记录,请你推测出转换率 V 的最小值和最大值分别可能是 多少,题目保证评测数据不存在无解的情况。
思路:因为题目肯定能保证有解,所以每条记录都要找到本记录的最值,然后从满足每条记录的最小值中取最大值,从满足每条记录的最大值中取最小值即可。
#include<bits/stdc++.h>
using namespace std;
int n,a,b,x=-1,y=1e9;
int main(){
cin>>n;
for(int i=0;i<n;i++){
cin>>a>>b;
x=max(x,a/(b+1)+1); //x为第一条到当前记录能满足最小值的最大值 a/(b+1)+1表示当前记录能满足的最小值
y=min(y,a/b); //y为第一条到当前记录能满足最大值的最小值 a/b 表示当前记录能满足的最大值
}
cout<<x<<" "<<y;
return 0;
}
D.飞机降落
N 架飞机准备降落到某个只有一条跑道的机场。其中第 i 架飞机在 Ti 时刻 到达机场上空,到达时它的剩余油料还可以继续盘旋 Di 个单位时间,即它最早 可以于 Ti 时刻开始降落,最晚可以于 Ti + Di 时刻开始降落。降落过程需要 Li 个单位时间。 一架飞机降落完毕时,另一架飞机可以立即在同一时刻开始降落,但是不 能在前一架飞机完成降落前开始降落。 请你判断 N 架飞机是否可以全部安全降落。
思路 DFS全排序,把所有的降落顺序都走一遍,全部降落成功说明有这一情况。
#include <bits/stdc++.h>
using namespace std;
const int N = 10;
bool s[N];
int n;
struct plane
{
int t, d, l; //定义结构体
}p[N];
bool dfs(int u, int last)
{
if(u == n) return true;
//如果走到这步,说明该选择的排序都可以满足所以飞机,直接返回true;如果有一项不满足是走不到这里的
for(int i = 0; i < n; i ++) //全排序循环,这里指把所有降落的飞机的顺序全部排一遍;
{
int t = p[i].t, d = p[i].d, l = p[i].l;
if(!s[i] && t + d >= last) //如果当前满足降落时间大于所给的降落时间,说明可以降落
{
s[i] = true; //当前排序说明已经走过了
if(dfs(u + 1, max(t, last) + l)) return true;
//u+1开始下一辆;max(t,last)当前降落时间和上次降落时间取个最大值,再加上当前所需的降落时间;
//如果不满足下一架飞机,则直接false;准备恢复现场; 然后return false;
s[i] = false; //恢复现场
}
}
return false;
}
int main()
{
int T;
cin >> T;
while(T --)
{
cin >> n;
memset(st, false, sizeof st);
for(int i = 0; i < n ; i ++)
{
int t, d, l;
scanf("%d%d%d", &t, &d, &l);
p[i] = { t, d, l}; //给结构体赋值
}
if(dfs(0, 0)) puts("YES"); //满足返回YES,否则NO;
else puts("NO");
}
return 0;
}
E: 接龙数列
对于一个长度为 K 的整数数列:A1, A2, . . . , AK,我们称之为接龙数列当且 仅当 Ai 的首位数字恰好等于 Ai−1 的末位数字 (2 ≤ i ≤ K)。 例如 12, 23, 35, 56, 61, 11 是接龙数列;12, 23, 34, 56 不是接龙数列,因为 56 的首位数字不等于 34 的末位数字。所有长度为 1 的整数数列都是接龙数列。 现在给定一个长度为 N 的数列 A1, A2, . . . , AN,请你计算最少从中删除多少 个数,可以使剩下的序列是接龙序列?
思路:动态规划,因为范围较大,所以需要边处理边满足条件,取得能是接龙数列的最大值,然后让总数减去这个最大值得到需要删除的个数。
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
int g[10];
int main()
{
int res=0;
int n;
cin>>n;
for(int i=0;i<n;++i)
{
string s;
cin>>s;
int l=s[0]-'0',r=s[s.size()-1]-'0';
int f=max(1,g[l]+1);
g[r]=max(g[r],f);
res=max(res,f);
}
cout<<n-res<<endl;
return 0;
}