Bestcoder round#33 解题报告
2016-05-20 00:26
197 查看
1001
简单的进制转换问题。#include<cstdio> #include<cstring> #include<cstdlib> #include<cmath> #include<iostream> #include<algorithm> using namespace std; char p[36]; int a[310]; char s[310]; int n,b,l; int main() { for (int i=0;i<=9;i++) p[i]=(char)(i+'0'); for (int i=10;i<36;i++) p[i]=(char)(i-10+'a'); while (scanf("%d %d",&n,&b)==2) { memset(a,0,sizeof(a)); for (int i=1;i<=n;i++) { scanf("%s",s); l=strlen(s); int pos=0; for (int j=l-1;j>=0;j--) { int d; if (s[j]>='0'&&s[j]<='9') d=s[j]-'0'; else d=s[j]-'a'+10; a[pos++]+=d; } } int flag=0; for (int i=0;i<=220;i++) { a[i]%=b; if (a[i]) flag=i; } for (int i=flag;i>=0;i--) printf("%c",p[a[i]]); printf("\n"); } return 0; }
1002
我们所选取的a[i]一定是整个序列中最大或者最小的,这两种情况完全等价。不妨考虑a[i]是最大数这种情况:选出a[i]后,剩下有n-1个数,对于每个数都有两种放法,放在a[i]左侧或者放在a[i]右侧,一共2n−1种。如果每个数放左还是放右已经确定了,那么显然整个序列也就确定了。那么总方案数应该为2n种。但是会有重复:a[i]最大,且左边没有数,和a[i]最小,且右边没有数;a[i]最大,且右边没有数,和a[i]最小,且左边没有数。所以ans应该为2n−2 。但是我们需要注意特判n=1的情况,此时答案应该为1 。#include<cstdio> #include<cstring> #include<cstdlib> #include<cmath> #include<iostream> #include<algorithm> using namespace std; typedef long long LL; LL p; LL n; LL multi(LL a, LL b) { LL ret=0; while(b) { if(b&1) ret=(ret+a)%p; a=(a+a)%p; b>>=1; } return ret; } LL pow_mod(LL a,LL b) { LL ret=1; while(b) { if(b&1) ret=multi(ret,a)%p; a=multi(a,a)%p; b>>=1; } return ret; } int main() { while (cin>>n>>p) { if (n==1) cout<<1%p<<endl; else { LL ans=pow_mod(2,n)-2; while (ans<0) ans+=p; cout<<ans<<endl; } } return 0; }
1003
简单的背包问题,不过注意物品的选取顺序有讲究。我们需要按照l[i]-t[i]的大小,从小到大进行排序(满足拓扑序),之后就跟最简单的01背包完全一致了。#include<cstdio> #include<cstring> #include<cstdlib> #include<cmath> #include<iostream> #include<algorithm> using namespace std; typedef long long LL; LL f[1100000]; int l[40],v[40],t[40],b[40],a[40]; int cmp(int x,int y) { return b[x]<b[y]; } int n,w,maxx,tt; int main() { while (scanf("%d %d",&n,&w)==2) { memset(f,0,sizeof(f)); maxx=tt=0; for (int i=1;i<=n;i++) { scanf("%d %d %d",&t[i],&v[i],&l[i]); a[i]=i; maxx=max(maxx,l[i]); tt+=t[i]; b[i]=l[i]-t[i]; } tt+=maxx; sort(a+1,a+1+n,cmp); for (int i=1;i<=n;i++) { int ll=max(t[a[i]],l[a[i]]); for (int j=tt;j>=ll;j--) { f[j]=max(f[j],f[j-t[a[i]]]+(LL)v[a[i]]); } } int flag=0; for (int i=1;i<=tt;i++) { if (f[i]>=w) { flag=1; printf("%d\n",i); break; } } if (!flag) printf("zhx is naive!\n"); } return 0; }
1004
很容易想到二分,设答案为ans。那么我们需要判断是否存在一组wb,hb,wg,hg,满足wb∗hb+wg∗hgwb+wg≥ans,即ans∗wb−wb∗hb+ans∗wg−wg∗hg≤0
显然此时我们是要维护斜率,由于询问是在树上的一个简单路径。所以我们需要将树树链剖分,然后在每个线段树上建凸包,在凸包内二分。思路很简单,但是由于太弱,还没调试成功,为了打卡,先把题解放在这里,等以后过了,再把代码贴上来。
相关文章推荐
- Swift概览
- 华为云服务产品之精华问题大集烩(三)
- 练习三1011
- 学习进度条
- GitHub详细教程
- thinkphp
- 如何高效利用GitHub
- 融云库RongIMKit19个错误 RongIMLIB等7个错误的解决方法
- Python解析模块argparse
- gcc命令
- github简单使用教程
- Mac环境下svn的使用
- 给hexo添加评论系统
- 阔谈-首篇
- mybatis jar包版本问题
- SpringBoot框架初接触
- LeetCode OJ 27. Remove Element
- 不想放弃的绝望中,求纠正错误,只过了两个点,真的在用链表。求解。。
- Swift 提升性能的秘密 Part 1 - Measure
- 最新Activity与Fragment完全理解