codeforces Hello 2018(A-E)
2018-01-17 14:51
344 查看
A题
B题
C题
D题
E题
因为m的范围只有1e8,所以,只用看n小于30的范围就行了
可以用bfs或者dfs来做呀,遍历一遍。
这里要注意的是dfs中不要掉return呀,虽然有时候本地机器会出来正确结果,但是到编译的时候可能会wa,或者会出现段错误想起来当初建树过程递归(指针)一个return都没写,程序没出问题,还是出了正确结果,可能知道我在想什么吧...
开始的想法就是贪心,但是wa了,
然后感觉好像完全背包,看一眼范围,不行
然后感觉还是贪心…
思路就是按照单价排序,先尽量拿单价少的,如果超过了l容量,那么记录一下当前值,然后每次超过了,都记录一下值,最小的就是结果了
wa,,,
最后发现竟然是排序函数的问题???
如果单价相同的话,那么就按照体积从大道小,否则按照单价从小到大
去掉对单价相同的考虑就A了…
还有一个想法是和二进制有关的,感觉很巧妙呀~
求m最大为多少。
开始看了几遍题目都没懂….
这个的话,就是优先级队列,队列中放的就是解决的问题,且ai>=q.size();
这个可以dp
F[i]:最后一步操作是!
T[i]:最后一步操作是&
E[i]:最后一步操作是|
状态转移:
F[i]可以转移到F[i^255]
F[i]可以直接转移到T[i]
T[i]可以转移到E[i]
E[i]可以转移到F[i](通过())
看不懂没关系,直接看代码,代码写的很清楚~
ps:临时变量作为引用型参数的时候要加const
还有一种做法最小生成树转移,感觉和这个差不多,也是先将所有值都计算出来,将这里的while(1)改成while(!q.empty()),然后是一样的转移
9dc0
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
相关文章推荐
- Codeforces Hello 2018——Party Lemonade(DP)
- Codeforces Hello 2018 C. Party Lemonade(思维)
- codeforces Hello 2018(A-E)
- codeforces Hello 2018 B. Christmas Spruce
- Codeforces Hello 2018 D. Too Easy Problems (二分)
- codeforces Hello 2018(A-E)
- codeforces Hello 2018(A-E)
- Christmas Spruce—codeforces(hello_2018)
- Codeforces Hello 2018
- codeforces Hello 2018(A-E)
- codeforces Hello 2018 C. Party Lemonade(贪心)
- codeforces Hello 2018 C. Party Lemonade(DP+思维)
- Codeforces Hello 2018
- Codeforces Hello 2018 C. Party Lemonade 贪心、优先队列
- Codeforces Hello 2018 [ABC]
- Codeforces Hello 2018 - A - Modular Exponentiation
- codeforces Hello 2018(A-E)
- Codeforces Hello 2018 - B - Christmas Spruce
- Codeforces Hello 2018
- codeforces Hello 2018(A-E)