bzoj上的一眼水题(上)
来源:互联网 发布:javascript var obj 编辑:程序博客网 时间:2024/06/07 20:29
一眼水题orz
(截至2017-2-16前在bzoj上做的一眼水题)
bzoj上的题目链接形式:
http://www.lydsy.com/JudgeOnline/problem.php?id=题号
例如: 题号1000链接:
http://www.lydsy.com/JudgeOnline/problem.php?id=1000
(之后每道题就不粘链接了)
1000.A+B Problem
题解:a+b
代码:
#include<cstdio>using namespace std;int main(){ int a,b; scanf("%d%d",&a,&b); printf("%d\n",a+b); return 0;}
1008.越狱
题解:用总方案数减去不会越狱的方案数.
总方案数:m^n
不合法方案数:第一个房间m种选择,后面n-1个犯人每人有m-1种选择,即 m*(m-1)^(n-1)
快速幂计算,两者相减即为答案。
代码:
#include<bits/stdc++.h>const int MOD=100003;long long qpow(long long x,long long n){ long long ret=1; while(n) { if(n&1) ret=ret*x%MOD; x=x*x%MOD; n>>=1; } return ret;}using namespace std;int main(){ long long m,n; scanf("%lld%lld",&m,&n); long long ans=(qpow(m,n)-qpow(m-1,n-1)%MOD*m%MOD+MOD)%MOD; printf("%lld\n",ans); return 0;}
1012.最大数maxnumber
题解:线段树。我不会告诉你这道题可以队列暴力
代码:
#include<iostream>#include<cstdio>#include<algorithm>#include<cstring>#include<cmath>#include<cstdlib>#include<ctime>using namespace std;int seq[200005];char c[5];int main(){ int m,d,t=0,cnt=0,l,n; scanf("%d%d",&m,&d); while(m--) { scanf("%s",c); if(c[0]=='Q') { scanf("%d",&l); t=seq[cnt+1-l]; printf("%d\n",t); } if(c[0]=='A') { scanf("%d",&n); cnt++;seq[cnt]=(n+t)%d; for(int i=cnt-1;i>0;i--) { if(seq[cnt]<seq[i])break; seq[i]=seq[cnt]; } } } return 0;}
1022.小约翰的游戏John
题解:Nim游戏。。。SG函数策略证明什么的网上有,算个异或和(全为1特判)
代码:
#include<bits/stdc++.h>using namespace std;int main(){ int t,n,a,sg; bool pd; scanf("%d",&t); while(t--){ scanf("%d",&n); sg=0;pd=0; for(int i=1;i<=n;i++) { scanf("%d",&a); sg^=a; if(a!=1)pd=1; } if((sg&&pd)||(!sg&&!pd)) puts("John"); else puts("Brother"); } return 0;}
1034.泡泡堂BNB
题解:贪心,得分最多是排序后从蔃到蒻排名相同的比赛,如果比不过就用最蒻的来比赛,得分最少的就是对方得分最多的情况用总分减去即可。
代码:
#include<bits/stdc++.h>using namespace std;int work(int a[],int b[],int n){ int la=1,lb=1,ra=n,rb=n,ans=0; while(la<=ra&&lb<=rb) { if(a[la]>b[lb])++la,++lb,ans+=2; else if(a[ra]>b[rb])--ra,--rb,ans+=2; else{ if(a[la]==b[rb])ans++; ++la,--rb; } } return ans;}int a[100005],b[100005];int main(){ int n; scanf("%d",&n); for(int i=1;i<=n;++i)scanf("%d",&a[i]); for(int i=1;i<=n;++i)scanf("%d",&b[i]); sort(a+1,a+1+n);sort(b+1,b+1+n); printf("%d %d\n",work(a,b,n),2*n-work(b,a,n)); return 0;}
1047.理想的正方形
题解:滑动窗口+单调队列。
然而苯蒟蒻:暴力
代码:
#include<bits/stdc++.h>#define INF 2e9using namespace std;int mat[1005][1005],minn[1005][1005],maxn[1005][1005];int main(){ //freopen(".in","r",stdin); //freopen(".out","w",stdout); int a,b,n,ans=INF,nowmax,nowmin; scanf("%d%d%d",&a,&b,&n); for(int i=1;i<=a;++i) for(int j=1;j<=b;++j) scanf("%d",&mat[i][j]); memset(minn,0x7f,sizeof(minn)); for(int i=1;i<=a;++i) for(int j=1;j<=b-n+1;++j) for(int k=j;k<=j+n-1;++k) { maxn[i][j]=max(maxn[i][j],mat[i][k]); minn[i][j]=min(minn[i][j],mat[i][k]); } for(int i=1;i<=a-n+1;++i) for(int j=1;j<=b-n+1;++j) { nowmax=0,nowmin=INF; for(int k=i;k<=i+n-1;++k) { nowmax=max(nowmax,maxn[k][j]); nowmin=min(nowmin,minn[k][j]); if(nowmax-nowmin>=ans)break; } if(nowmax-nowmin<ans)ans=nowmax-nowmin; } printf("%d\n",ans); return 0;}
1087.互不侵犯King
题解:基础状压dp,记一下每行的状态,状压01表示放没放转成二进制数,cnt表示一行的棋子个数,预处理出一行相邻格子不能放,即不可行的状态lgl(可行)和upn(相邻),每行状态只跟上一行有关,dp即可。
初始化:dp[1][cnt[i]][i] = 1 (0<=i<2^n, lgl[i])
方程式:dp[i][p+cnt[j]][j] = dp[i][p][l] (2<=i<=n, 0<=j,l<2^n, cnt[l]<=p<=k-cnt[j], lgl[j]&&lgl[l]&&upn[j][l])
代码:
#include <bits/stdc++.h>using namespace std;int cnt[515];bool lgl[515], upn[515][515];long long dp[11][85][515];int main (){ //freopen (".in", "r", stdin); //freopen (".out", "w", stdout); int n, k; long long ans = 0; scanf ("%d%d", &n, &k); int nst = 1 << n; for (int i = 0; i < nst; ++ i) if (!(i & (i >> 1))) { lgl[i] = 1; int sum = 0; for (int j = i; j; j >>= 1) sum += j & 1; cnt[i] = sum; } for (int i = 0; i < nst; ++ i) if (lgl[i]) for (int j = 0; j < nst; ++ j) if (lgl[j] && !(i & j) && !(i & (j >> 1)) && !((i >> 1) & j)) upn[i][j] = 1; for (int i = 0; i < nst; ++ i) if (lgl[i]) dp[1][cnt[i]][i] = 1; for (int i = 2; i <= n; ++ i) for (int j = 0; j < nst; ++ j) if(lgl[j]) for (int l = 0; l < nst; ++ l) if (lgl[l] && upn[j][l])for (int p = cnt[l]; p <= k - cnt[j]; ++ p) dp[i][p + cnt[j]][j] += dp[i - 1][p][l]; for (int i = 0; i < nst; ++ i) ans += dp[n][k][i]; printf ("%lld\n", ans); return 0;}
1088.扫雷Mine
题解:递推思想,a数组记录第二行格子相邻炸弹数,f数组表示要求的第一行格子相邻炸弹数,可以递推得f[i+1]=a[i]-f[i]-f[i-1]
,分类讨论a[1], f[1], f[2]的情况,统计方案数。
代码:
#include<bits/stdc++.h>using namespace std;int n,ans;int a[10001],f[10001];bool jud(){ for(int i=2;i<=n;i++) { f[i+1]=a[i]-f[i]-f[i-1]; if(f[i+1]<0)return 0; } if(a[n]-f[n-1]-f[n]!=0)return 0; return 1;}int main(){ scanf("%d",&n); for(int i=1;i<=n;i++)scanf("%d",&a[i]); if(a[1]==0)ans+=jud(); else if(a[1]==1) { f[1]=1;ans+=jud(); memset(f,0,sizeof(f)); f[2]=1;ans+=jud(); } else {f[1]=f[2]=1;ans+=jud();} printf("%d",ans); return 0;}
1192.鬼谷子的钱袋
题解:表示成二进制数是最少的,就是求m的二进制位数。
代码:
#include<bits/stdc++.h>using namespace std;int main(){ int m,ans=0; scanf("%d",&m); while(m) { m>>=1; ans++; } printf("%d\n",ans); return 0;}
1193.马步距离
题解:贪心+暴搜
距离终点比较远的时候贪心:设终点与现在位置的横坐标差为xs,纵坐标差为ys,下一步位移的横纵坐标正负即xs。ys的符号;如果|xs|>|ys|,横坐标位移绝对值为2,纵坐标绝对值为1,否则反之。
移动到以终点为重心5*5范围内时,贪心会出现错误。此时采用暴搜即可。
代码:
#include <bits/stdc++.h>using namespace std;const int f[7][7] = { {0, 3, 2, 3, 2}, {3, 2, 1, 2, 3}, {2, 1, 4, 3, 2}, {3, 2, 3, 2, 3}, {2, 3, 2, 3, 4}};int main (){ //freopen (".in", "r", stdin); //freopen (".out", "w", stdout); int xp, yp, xs, ys, x, y, ans = 0; scanf ("%d%d%d%d", &xp, &yp, &xs, &ys); x = abs (xp - xs); y = abs (yp - ys); while (x > 4 || y > 4) { if (x < y) x -= 1, y -= 2; else x -= 2, y -= 1; x = abs (x); y = abs (y); ++ ans; } ans += f[x][y]; printf ("%d\n", ans); return 0;}
1199.汤姆的游戏
题解:标算应该是对于每个点二分一下判断,或者线段树一类。
这道题可以用队列:先把圆当成它的边平行于坐标轴的外接正方形,转换成矩形。再使用队列维护一下在每个矩形x范围内的点,暴力判断y是否在范围内;如果是圆还要判断一下到圆心距离和半径的关系。
代码:
#include<bits/stdc++.h>using namespace std;struct point{double x,y;int bh;}p[10005];struct rect{point a,b;}re[250005];struct circ{point o;double r;}ci[250005];int ans[10005],que[10005];char c[2];double pf(double q){return q*q;}bool cmp(point A,point B){return A.x<B.x;}bool cmpr(rect A,rect B){ if(A.a.x<B.a.x)return 1; if(A.a.x>B.a.x)return 0; return A.b.x<B.b.x;}bool cmpc(circ A,circ B){ if(A.o.x-A.r<B.o.x-B.r)return 1; if(A.o.x-A.r>B.o.x-B.r)return 0; return A.o.x+A.r<B.o.x+B.r;}int main(){ int n,m,nr=0,nc=0,now,head,tail; scanf("%d%d",&n,&m); for(int i=1;i<=n;++i) { scanf("%s",c); if(c[0]=='r'){++nr;scanf("%lf%lf%lf%lf",&re[nr].a.x,&re[nr].a.y,&re[nr].b.x,&re[nr].b.y);} if(c[0]=='c'){++nc;scanf("%lf%lf%lf",&ci[nc].o.x,&ci[nc].o.y,&ci[nc].r);} } for(int i=1;i<=m;++i) {scanf("%lf%lf",&p[i].x,&p[i].y);p[i].bh=i;} sort(p+1,p+m+1,cmp); sort(re+1,re+nr+1,cmpr); sort(ci+1,ci+nc+1,cmpc); now=1,head=0,tail=-1; for(int i=1;i<=nr;++i) { while(p[now].x<=re[i].a.x&&now<=m)++now; while(p[que[head]].x<=re[i].a.x&&head<=tail)++head; while(p[now].x<re[i].b.x&&now<=m){++tail;que[tail]=now;++now;} for(int j=head;j<=tail;++j) { if(p[que[j]].x>re[i].a.x &&p[que[j]].x<re[i].b.x &&p[que[j]].y>re[i].a.y &&p[que[j]].y<re[i].b.y) ++ans[p[que[j]].bh]; } } now=1,head=0,tail=-1; for(int i=1;i<=nc;++i) { while(p[now].x<=ci[i].o.x-ci[i].r&&now<=m)++now; while(p[que[head]].x<=ci[i].o.x-ci[i].r&&head<=tail)++head; while(p[now].x<ci[i].o.x+ci[i].r&&now<=m){++tail;que[tail]=now;++now;} for(int j=head;j<=tail;++j) { if(pf(p[que[j]].x-ci[i].o.x)+pf(p[que[j]].y-ci[i].o.y)<pf(ci[i].r)) ++ans[p[que[j]].bh]; } } for(int i=1;i<=m;++i) printf("%d\n",ans[i]); return 0;}
1432.Function
题解:这个。。。苯蒟蒻也不是太会,找规律。发现如果这些函数以一种方式排列,第k层有2k段,当然可以将第k层转化为n-k+1层,两种方法取min,注意n==1时特判。
代码:
#include<bits/stdc++.h>using namespace std;int main(){ int n,k; scanf("%d%d",&n,&k); if(n==1)puts("1"); else printf("%d\n",2*min(k,n-k+1)); return 0;}
1800.fly 飞行棋
题解:n<=20???这个数据范围简直是暴殄天物!
O(n^4)做法:暴力枚举哪4个点,判断顺次两点之间的圆弧,相对的是否相等。
O(n^2)做法:预处理圆弧长度前缀和,枚举两个点看之间的圆弧是否为周长的一半,统计直径个数,每两个不同的直径对应着一个矩形。
O(n)做法:计算直径个数时无需枚举,按顺时针顺序处理即可。
代码 O(n^2):
#include<bits/stdc++.h>using namespace std;int sum[25];int main(){ int n,d=0,a; scanf("%d",&n); for(int i=1;i<=n;i++) { scanf("%d",&a); sum[i]=sum[i-1]+a; } for(int i=1;i<n;i++) for(int j=i+1;j<=n;j++) if(sum[j]-sum[i]==sum[n]>>1) d++; printf("%d\n",d*(d-1)/2); return 0;}
1968.COMMON 约数研究
题解:稍微逆向思维一下,对于每一个1<=i<=n,在<=n的范围内是n/i个数的约数,直接统计对答案的贡献即可。答案为:
代码:
#include<bits/stdc++.h>using namespace std;int main(){ int n,ans=0; scanf("%d",&n); for(int i=1;i<=n;i++) ans+=n/i; printf("%d\n",ans); return 0;}
2257.瓶子和燃料
题解:感性认识一下,操作能的得到的最小正体积是这些瓶子容量的gcd(好像有一个叫裴蜀定理的东西,表示并不会),把这n个数的所有约数放在一起排序,找到最大的出现次数大于k的就约数即为答案。
代码:
#include<bits/stdc++.h>using namespace std;int Div[2000005];int main(){ int n,num=0,cnt=0,v,k; scanf("%d%d",&n,&k); for(int i=1;i<=n;i++) { scanf("%d",&v); for(int j=1;j*j<=v;j++) if(v%j==0) { if(j*j<v){Div[++num]=j;Div[++num]=v/j;} else Div[++num]=j; } } sort(Div+1,Div+num+1); for(int i=num;i>=1;i--) { if(Div[i]!=Div[i+1])cnt=1; else cnt++; if(cnt>=k){printf("%d\n",Div[i]);break;} } return 0;}
- bzoj上的一眼水题(上)
- bzoj 2406: 矩阵 (有上下界的网络流)
- bzoj 1041: [HAOI2008]圆上的整点 (数学)
- #bzoj-Balic2001#棋盘上的骑士(Hungary)
- bzoj 1041 圆上的整点
- bzoj 1041 圆上的整点
- 【BZOJ 1041】 [HAOI2008]圆上的整点
- bzoj 1041: [HAOI2008]圆上的整点
- BZOJ 1041: [HAOI2008]圆上的整点
- [数学] BZOJ 4544 椭圆上的整点
- 【BZOJ】1041: [HAOI2008]圆上的整点
- BZOJ P1041[HAOI2008]圆上的整点
- [BZOJ 1041] 圆上的整点
- bzoj 1041: [HAOI2008]圆上的整点
- bzoj 1041 [HAOI2008]圆上的整点
- 老公扭脸看了我一眼说“上一辈子你也是这样说的……
- bzoj上用python注意
- bzoj 3876 [Ahoi2014]支线剧情(有上下界的最小费用流)
- Javascript对象与继承
- PHP+MySQL+Dreamweaver动态网站开发_第一个PHP程序
- 面向过程与面向对象比较之tab选项卡切换
- 将eclipse开发的web项目导入到myeclipse
- Windows下使用grep命令(以及其它部分Linux命令)
- bzoj上的一眼水题(上)
- Object-C 中各数据类型转换 NSData NSMutableData NSString Byte UIImage 合并音频
- 前端开发者应该知道的 CSS 小技巧
- Android获取当前时间
- 项目管理利器--Maven
- PAT甲级1121
- CentOs6.5安装高版本git
- stm32 can波特率计算
- 6、Power Map—实例:柱状图按月展示数据变动