您的位置:首页 > 其它

codeforces Hello 2018(A-E)

2018-01-17 14:51 423 查看
A题

B题

C题

D题

E题

A题

题意:求m %2n的值

因为m的范围只有1e8,所以,只用看n小于30的范围就行了

B题

题意:一个树中,若非叶子节点没有大于或等于3个叶子节点相连的话,输出No,否则输出Yes

可以用bfs或者dfs来做呀,遍历一遍。

这里要注意的是dfs中不要掉return呀,虽然有时候本地机器会出来正确结果,但是到编译的时候可能会wa,或者会出现段错误想起来当初建树过程递归(指针)一个return都没写,程序没出问题,还是出了正确结果,可能知道我在想什么吧...

C题

题意:柠檬水,不同容量,会有不同价格,问要买不少于L升柠檬水,最少需要花的钱数.给定对应第i容量的价格,容量是2i−1,每种容量可以买任意次

开始的想法就是贪心,但是wa了,

然后感觉好像完全背包,看一眼范围,不行

然后感觉还是贪心…

思路就是按照单价排序,先尽量拿单价少的,如果超过了l容量,那么记录一下当前值,然后每次超过了,都记录一下值,最小的就是结果了

wa,,,

最后发现竟然是排序函数的问题???

bool cmp(node a1,node a2)
{
if(abs(a1.per-a2.per)<eps) return a1.v>a2.v;
return a1.per<a2.per;
}


如果单价相同的话,那么就按照体积从大道小,否则按照单价从小到大

去掉对单价相同的考虑就A了…

还有一个想法是和二进制有关的,感觉很巧妙呀~

#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <vector>
#include <queue>
#include <stack>

using namespace std;
#define mem(a,b) memset(a,b,sizeof(a))
#define ll long long
const double eps = 1e-6;
const ll inf = 1e18;
ll a[100];
int main()
{
int n,l;
scanf("%d %d",&n,&l);
for(int i=0;i<n;i++)
scanf("%I64d",&a[i]);
for(int i=1;i<n;i++)
a[i]=min(a[i],a[i-1]*2ll);
for(int i=n-2;i>=0;i--)
a[i]=min(a[i],a[i+1]);
for(int i=n;i<=30;i++)
a[i]=a[i-1]*2ll;
ll ans = 0;
int i=0;
while(l)
{
if(l&1) ans = ans + a[i];
i++;
if(ans>a[i]) ans = a[i];
l=l/2;
}
if(a[i]<ans) ans = a[i];
printf("%I64d\n",ans);
return 0;
}


D题

题意:就是有n个问题,限时是T,给出每个问题的ai和ti,ti表示需要消耗的时间。如果在T时间内解决了k个问题,那么m=解决的问题.ai>=k,的数量

求m最大为多少。

开始看了几遍题目都没懂….

这个的话,就是优先级队列,队列中放的就是解决的问题,且ai>=q.size();

#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <vector>
#include <queue>
#include <stack>

using namespace std;
#define mem(a,b) memset(a,b,sizeof(a))
#define ll long long
const int maxn = 2*100000+10;
struct node {
int ai,ti,id;
operator < (const node&temp)const {
return ai>temp.ai;
}
}a[maxn];
priority_queue<node>q;
bool cmp(node a1,node a2)
{
return a1.ti<a2.ti;
}
int main()
{
int n,t;
scanf("%d %d",&n,&t);
for(int i=1;i<=n;i++){
scanf("%d %d",&a[i].ai,&a[i].ti);
a[i].id = i;
}
sort(a+1,a+n+1,cmp);
int i;
for(i=1;i<=n;i++)
{
t-=a[i].ti;
if(t<0) break;
q.push(a[i]);
}
t+=a[i].ti;
while(!q.empty())
{
node a1 = q.top();
if(a1.ai<(q.size())) {q.pop();t+=a1.ti;}
else break;
}
for(;i<=n;i++)
{
int temp = t-a[i].ti;
if(temp<0) break;
if(a[i].ai<(q.size()+1)) continue;//这个要先判断,然后才能加进去
q.push(a[i]);
t=temp;
node a1 = q.top();
if(a1.ai<(q.size())) {q.pop();t+=a1.ti;}
}
printf("%d\n",q.size());
printf("%d\n",q.size());
if(q.size()>=1){
node a1 = q.top();
printf("%d",a1.id);q.pop();
while(!q.empty())
{
a1 = q.top();
printf(" %d",a1.id);
q.pop();
}
}
printf("\n");
return 0;
}


E题

题意:x=00001111b,y=00110011b,z=01010101b,有三种操作,按照优先级从高到题分别是!,&,|,还有一个(),给n个值,问对x,y,z进行怎样的操作可以变成给的值,输出表达式。

这个可以dp

F[i]:最后一步操作是!

T[i]:最后一步操作是&

E[i]:最后一步操作是|

状态转移:

F[i]可以转移到F[i^255]

F[i]可以直接转移到T[i]

T[i]可以转移到E[i]

E[i]可以转移到F[i](通过())

看不懂没关系,直接看代码,代码写的很清楚~

/*
by:sllsll
*/
#include <iostream>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <cstdio>
#include <vector>
#include <map>
#include <set>

using namespace std;
#define inf 0x3f3f3f3f
#define ll long long
#define mem(a,b) memsert(a,b,sizeof(a))
#define rep(a,b) for(int i=(a);i<(b);i++)
const int maxn = 1e5+10;
string F[maxn],T[maxn],E[maxn];
int x = 15,y=51,z=85;
int flag=0;
void fz(string&a,const string& b)
{
if(a=="")
{
flag=1;
a=b;return;
}
int size1 = a.length(),size2 = b.length();
//最小字典序
if(size1>size2) a = b,flag=1;
else if(size1==size2)
if(a>b)a=b,flag=1;

}
void dp()
{
F[x]='x',F[y]='y',F[z]='z';
while(1)
{
flag=0;
rep(0,256)
if(F[i]!="")
fz(F[i^255],'!'+F[i]);
for(int i=0;i<256;i++)
if(F[i]!=""){
fz(T[i],F[i]);
for(int j=0;j<256;j++)
if(T[j]!="")
fz(T[i&j],F[i]+"&"+T[j]);
}
for(int i=0;i<256;i++)
if(T[i]!=""){
fz(E[i],T[i]);
for(int j=0;j<256;j++)
if(E[j]!="")
fz(E[i|j],T[i]+"|"+E[j]);
}
for(int i=0;i<256;i++)
if(E[i]!=""){
fz(F[i],"("+E[i]+")");
}
if(!flag) break;
}
}
int d[10]={128,64,32,16,8,4,2,1};
int change(string str)
{
int ans = 0;
for(int i=0;i<8;i++)
{
if(str[i]=='1') ans+=d[i];
}
return ans;
}
int main()
{
dp();
int T;
scanf("%d",&T);
while(T--)
{
string str;
cin>>str;
int n=change(str);
cout<<E
<<endl;
}
return 0;
}


ps:临时变量作为引用型参数的时候要加const

还有一种做法最小生成树转移,感觉和这个差不多,也是先将所有值都计算出来,将这里的while(1)改成while(!q.empty()),然后是一样的转移

9dc0
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: