Codeforces Round #319 (Div. 1) 简要记录
来源:互联网 发布:419是什么意思网络用语 编辑:程序博客网 时间:2024/06/05 16:17
A. Vasya and Petya’s Game
题意:
Vasya和Petya在玩一个游戏。
Vasya在1~n中任意选一个数x,并且Petya要来猜这个数x。
Petya可以进行诸如此类的询问:”x能否被y整除”,Vasya只会回答yes或者no。
询问:
Petya最少需要问几次才能确定数x,并且输出他询问的数都是什么,有多种顺序输出一种即可。
解析:
这显然是个找规律题…
我们发现对于一个能够分出来两个不同质因数的数我们只要对质因数及质因数的几次幂进行询问即可确定该数。
所以我们把目光放在质因数上。
假设我们询问了n以下所有质因数的一次幂,形如
如果紧接着询问了所有质因数的二次幂,形如
所以经由上面的规律寻找大概猜测我们要询问所有质因子的x次幂,并且该质因子的x次幂小于等于n。
大概脑补可以想象正确性。
直接暴力搞就行(为了尊重题我写了个线性筛素数23333)
代码:
#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>#define N 1100using namespace std;int n;int cnt;int print[N];int tot;int prime[N];int v[N];void sieve(){ for(int i=2;i<=n;i++) { if(!v[i]) { prime[++tot]=i; } for(int j=1;j<=tot&&i*prime[j]<=n;j++) { v[i*prime[j]]=1; if(i%prime[j]==0)continue; } }}int main(){ scanf("%d",&n); sieve(); for(int i=1;i<=tot;i++) { int tmp=prime[i]; while(tmp<=n) { print[++cnt]=tmp; tmp*=prime[i]; } } printf("%d\n",cnt); for(int i=1;i<=cnt;i++)printf("%d ",print[i]); puts("");}
B. Invariance of Tree
题意:
有一棵大小为n的无向树,我们称一棵树
询问:
给定序列求该树,不存在则输出NO,否则输出YES并且输出任意一种情况。
解析:
既然是一棵树,那么一定无环,也就是说不能没有大小为1或者2的置换,如果没有的话该树一定存在环,所以我们只需要寻找是否存在大小为1或者2的置换就好了。
如果存在大小为1的置换的话,即把所有其他的点连向它即可。
如果不存在大小为1的置换,反而存在大小为2的置换的话,首先将二者的边连上。
然后枚举其他置换。
我们发现其他置换的奇数点与第一个点连的话,那么所有的奇数点的下一个点都应该与第二个点连。(或者相反:D)
所以如果其他置换中有一个置换的大小为奇数则不能满足题意,输出NO。
否则按照如上方法输出边即可。
如果大小为1,大小为2的置换均不存在直接输出NO即可。
代码:
#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>#define N 100010using namespace std;int n;int a[N];int v[N];int sta[N];int tag[N];int main(){ scanf("%d",&n); for(int i=1;i<=n;i++)scanf("%d",&a[i]); int flag=0; for(int i=1;i<=n;i++) { if(a[i]==i) { flag=1; puts("YES"); for(int j=1;j<=n;j++) if(j!=i)printf("%d %d\n",i,j); break; } } if(flag)return 0; int tmp=-1; for(int i=1;i<=n;i++) { if(a[a[i]]==i) { tmp=i;break; } } if(tmp==-1){puts("NO");return 0;} v[tmp]=v[a[tmp]]=1; for(int i=1;i<=n;i++) { if(!v[i]) { int top=0; while(!v[i]) { sta[++top]=i; v[i]=1; i=a[i]; } if(top&1){puts("NO");return 0;} for(int j=1;j<=top;j++) { if(j&1)tag[sta[j]]=1; else tag[sta[j]]=2; } } } puts("YES"); printf("%d %d\n",tmp,a[tmp]); for(int i=1;i<=n;i++) { if(tag[i]==1)printf("%d %d\n",tmp,i); else if(tag[i]==2)printf("%d %d\n",a[tmp],i); }}
C. Points on Plane
题意:
左下角为
询问
求一个
定义
且
(md点少或者密集的时候不就是随便输出一个排列么2333)
解析
这个
我们把这个矩阵切成1000个如下的小矩阵。
然后我们将这些小矩阵按照顺序编上号。
所有奇数号内部的点按照纵坐标升序,偶数号内部的点按照纵坐标降序。
之后我们来考虑这种做法的最糟总和。
显然最糟跨越x是
跨越y最糟是每次内部
所以大概最糟可以达到
代码:
#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>#define N 1000100using namespace std;int n;struct Point{ int x,y,no; friend istream& operator >> (istream &_,Point &a) {scanf("%d%d",&a.x,&a.y);return _;}}pt[N];int get_dis(Point a,Point b){ return abs(a.x-b.x)+abs(a.y-b.y);}bool cmp(Point a,Point b){ return a.x<b.x;}bool cmp2(Point a,Point b){ return a.y<b.y;}bool cmp3(Point a,Point b){ return a.y>b.y;}int main(){ scanf("%d",&n); for(int i=1;i<=n;i++){cin>>pt[i];pt[i].no=i;} sort(pt+1,pt+n+1,cmp); int la=0,flag=1,lano=0; for(int i=1;i<=n;i++) { if(pt[i].x-la>=1000) { if(flag) sort(pt+lano+1,pt+i+1,cmp2); else sort(pt+lano+1,pt+i+1,cmp3); lano=i; flag^=1; la+=1000; } } for(int i=1;i<=n;i++)printf("%d ",pt[i].no); puts("");}
D. Flights for Regular Customers
题意:
我们能经过一条边的先决条件是我们之前已经走过了至少d条边。
询问:
1到n最少经过多少条边。
解析:
由于d很大,所以我们不能用?分层图?的想法强行搞过去。
但是我们观察到m的范围相当的小,也就是说,我们的对应的连边邻接矩阵最多也就是150个。
所以我们考虑是否可以按照边的di值升序排序,之后每一次转移一次
发现这种思路似乎可行。
于是我们设
如果当前有一个01矩阵代表走
然后我们扫到第
显然是走一次的矩阵的(
所以复杂度大概是
难道前功尽弃了嘛?(但是我感觉能过,出题人好像算错复杂度了)
并没有,因为这个矩阵始终是一个01矩阵,所以可以上bitset优化嘛23333
复杂度直接变成O(n^2*m*log_2d/32)
代码:
#include <cstdio>#include <bitset>#include <cstring>#include <iostream>#include <algorithm>#define N 160using namespace std;bitset<N>use[N],base[N],tmp[N];int dis[N][N];int n,m; struct Line{ int x,y,d;}edge[N];bool cmp(Line a,Line b){ return a.d<b.d;}void mul(bitset<N>*a,bitset<N>*b){ bitset<N>ret[N]; for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) if(a[i][j])ret[i]|=b[j]; for(int i=1;i<=n;i++)a[i]=ret[i];}void Quick_Power(bitset<N>*a,int b){ bitset<N>ret[N]; for(int i=1;i<=n;i++)ret[i][i]=1; while(b) { if(b&1)mul(ret,a); mul(a,a); b>>=1; } for(int i=1;i<=n;i++)a[i]=ret[i];}int ans;int main(){ ans=0x3f3f3f3f; scanf("%d%d",&n,&m); for(int i=1;i<=m;i++) { int x,y,d; scanf("%d%d%d",&x,&y,&d); edge[i].x=x,edge[i].y=y,edge[i].d=d; } sort(edge+1,edge+m+1,cmp); memset(dis,0x3f,sizeof(dis)); for(int i=1;i<=n;i++)use[i][i]=1,dis[i][i]=0; int la=0; for(int i=1;i<=m;i++) { int x=edge[i].x,y=edge[i].y,d=edge[i].d; for(int j=1;j<=n;j++) for(int k=1;k<=n;k++) dis[j][k]=min(dis[j][x]+1+dis[y][k],dis[j][k]); for(int j=1;j<=n;j++)tmp[j]=base[j]; Quick_Power(tmp,d-la); mul(use,tmp); for(int j=1;j<n;j++) { if(use[1][j]) { if(dis[j][n]!=0x3f3f3f3f) ans=min(ans,d+dis[j][n]); } } la=d; base[x][y]=1; } if(ans==0x3f3f3f3f)puts("Impossible"); else printf("%d\n",ans);}
E
去看PoPoQQQ题解吧,bzoj4025好像是这个的弱化,然而我是用lct强行搞过去的。
- Codeforces Round #319 (Div. 1) 简要记录
- CodeForces #Round 320 (div 1) 简要记录
- Codeforces Round #321 (Div. 2) 简要记录
- Codeforces Round #319 (Div. 1)
- Codeforces Round #259 (Div. 2) ABC简要题解
- Codeforces Round #319 (Div. 2)
- Codeforces Round #319 (Div. 2)
- [Codeforces #295(Div 1)]简要题解
- Codeforces #299 Div 1 简要题解
- Codeforces #292 Div 1 简要题解
- Codeforces #305 Div 1 简要题解
- Codeforces #290 Div. 1 简要题解
- Codeforces #286 Div 1 简要题解
- Codeforces #285 Div 1 简要题解
- Codeforces #284 Div 1 简要题解
- Codeforces #283 Div 1 简要题解
- Codeforces #278 Div 1 简要题解
- Codeforces #275 Div 1 简要题解
- 细数十大你不得不用的MySQL开发工具(1)
- POJ_3181 Dollar Dayz(dp,完全背包)
- 程序跳转到itunes商店
- 树形图计数 count题解
- gcc 和 arm-linux-gcc 编译器的默认搜索头文件路径
- Codeforces Round #319 (Div. 1) 简要记录
- 《活着中文版自序》感悟
- struts2 - There is no Action mapped for namespace [/login] and action name [login!loginInput] ...
- 深入理解ViewHolder
- excel中一列为公式计算得到的为文本,文本改为数值方法
- Git 中一些问题 : refusing to update checked out branch
- HDU 1261
- 5块钱买了个域名之后
- 在 ubuntu 14.04 上安装 YouCompleteMe( 自己看的操作笔记, 路人请勿看, 避免浪费时间 )