2017.10.15离线赛总结
来源:互联网 发布:js clear 方法 编辑:程序博客网 时间:2024/05/16 07:25
prime ——3784
思路:筛一筛质数,再将质数的倍数判一下,前缀和维护,然而这样就卡过去了…当然,正解无非就是更强大的筛法——线性筛。然而,老司机(小c)还有一种做法:将一个数除以其最大质因子,再判断商的最大质因子是否为本身这样似乎不用线性筛就更快了…那么我就将二者结合一下。
#include<bits/stdc++.h>#define REP(i,f,t) for(int i=(f),i##_end_=(t);i<=i##_end_;i++)#define LL long long#define N 10000005using namespace std;int Q,L,R;int sum[N];int mark[N],p[N],cnt;void Init(){ mark[1]=1; REP(i,2,N){ if(!mark[i])p[cnt++]=mark[i]=i; REP(j,0,cnt){ LL x=1ll*p[j]*i; if(x>=N)break; mark[x]=p[j]; if(!(i%p[j]))break; } } REP(i,2,N){ int x=i/mark[i]; sum[i]=sum[i-1]+(mark[x]==x); }} int main(){// freopen("prime.in","r",stdin);// freopen("prime.out","w",stdout); Init(); scanf("%d",&Q); while(Q--){ scanf("%d%d",&L,&R); printf("%d\n",sum[R]-sum[L-1]); } return 0;}
room ——3785
思路:bfs,不解释了,太明显了…But今天一开始切分(求稳),结果切着切着分就少了(tm着样例太水了)…However,这里要状压,常数有点大吧
#include<bits/stdc++.h>#define REP(i,f,t) for(int i=(f),i##_end_=(t);i<=i##_end_;i++)#define LL long long#define INF 0x3f3f3f3f#define N 10005#define M 10005#define K 15using namespace std;int n,m,k;struct P30{ int d[105][505]; void solve(){ memset(d,INF,sizeof(d)); REP(i,1,m){ int a,b; scanf("%d%d",&a,&b); d[a][b]=1; } d[1][1]=0; REP(l,1,n){ REP(i,1,n){ if(i==k)continue; REP(j,1,n){ if(i==j || j==k)continue; d[i][j]=min(d[i][j],d[i][l]+d[l][j]); } } } if(d[1][n]==INF)puts("No Solution"); else printf("%d\n",d[1][n]); }}p30;struct P50{ int d[N]; struct node{ int from,to; }es[M]; void Bellman(){ memset(d,INF,sizeof(d)); d[1]=0; while(1){ bool f=0; REP(i,1,m)if(d[es[i].from]!=INF && d[es[i].to]>d[es[i].from]+1)f=1,d[es[i].to]=d[es[i].from]+1; if(!f)break; } } void solve(){ REP(i,1,m)scanf("%d%d",&es[i].from,&es[i].to); Bellman(); if(d[n]==INF)puts("No Solution"); else printf("%d\n",d[n]); }}p50;struct P100{ int get[N],vis[N][1<<11]; struct edge{ int to,mark; }; vector<edge>E[M]; struct node{ int step,x,used; }; queue<node>Q; void bfs(){ Q.push((node){0,1,get[1]}); while(!Q.empty()){ node now=Q.front();Q.pop(); if(now.x==n){ printf("%d\n",now.step); exit(0); } REP(i,0,E[now.x].size()-1){ edge y=E[now.x][i]; if((now.used|y.mark)!=now.used)continue; node nxt; nxt.x=y.to; nxt.step=now.step+1; nxt.used=now.used|get[y.to]; if(vis[nxt.x][nxt.used])continue; vis[nxt.x][nxt.used]=nxt.step; Q.push(nxt); } } } void solve(){ REP(i,1,n){ int f; get[i]=0; REP(j,0,k-1){ scanf("%d",&f); if(f)get[i]|=1<<j; } } REP(i,1,m){ int a,b,f; scanf("%d%d",&a,&b); edge tmp; tmp.to=b; tmp.mark=0; REP(j,0,k-1){ scanf("%d",&f); if(f)tmp.mark|=1<<j; } E[a].push_back(tmp); } bfs(); puts("No Solution"); }}p100;int main(){// freopen("room.in","r",stdin);// freopen("room.out","w",stdout); scanf("%d%d%d",&n,&m,&k); if(!k && n<=100)p30.solve(); else if(!k && n<=1000)p50.solve(); else p100.solve(); return 0;}
light ——3786
思路:题意简单明了,就是求树上的两条路径的的重复的点,而且这里两点路径分别为a->b,c->b,那就更显然了,求出两两之间的lca分类讨论一下就出来了,这里分类讨论也是出奇的少,总而言之判一下路径是否覆盖——即a与b的lca和b与c的lca相等时,反之…
#include<bits/stdc++.h>#define REP(i,f,t) for(int i=(f),i##_end_=(t);i<=i##_end_;i++)#define DREP(i,f,t) for(int i=(f),i##_end_=(t);i>=i##_end_;i--)#define LL long long#define INF 0x3f3f3f3f#define N 200005#define S 20using namespace std;int n,Q,num;vector<int>E[N];int D[N],fa[S][N];struct PList{ int Dx; void dfs(int x,int f){ D[x]=D[f]+1; REP(i,0,E[x].size()-1){ int y=E[x][i]; if(y==f)continue; dfs(y,x); } } void solve(){ REP(i,1,n)if(E[i].size()<2)Dx=i; dfs(Dx,0); REP(i,1,Q){ int a,b,c; scanf("%d%d%d",&a,&b,&c); if(D[a]>=D[b] && D[c]>=D[b])printf("%d\n",min(D[a],D[c])-D[b]+1); else if(D[a]<=D[b] && D[c]<=D[b])printf("%d\n",D[b]-max(D[a],D[c])+1); else puts("1"); } }}p_list;struct P100{ void Up(int &x,int step){ DREP(i,S-1,0)if(step&(1<<i))x=fa[i][x]; } int Lca(int a,int b){ if(D[a]>D[b])swap(a,b); Up(b,D[b]-D[a]); if(a==b)return a; DREP(i,S-1,0)if(fa[i][a]!=fa[i][b])a=fa[i][a],b=fa[i][b]; return fa[0][a]; } void Init(){ REP(j,1,S-1) REP(i,1,n) fa[j][i]=fa[j-1][fa[j-1][i]]; } void dfs(int x,int f){ D[x]=D[f]+1; fa[0][x]=f; REP(i,0,E[x].size()-1){ int y=E[x][i]; if(y==f)continue; dfs(y,x); } } void solve(){ dfs(1,0); Init(); REP(i,1,Q){ int a,b,c; scanf("%d%d%d",&a,&b,&c); int lca1=Lca(a,b),lca2=Lca(b,c),lca3=Lca(a,c); printf("%d\n",lca1==lca2?D[lca3]-2*D[lca1]+D[b]+1:D[b]-max(D[lca1],D[lca2])+1); } }}p100;int main(){// freopen("light.in","r",stdin);// freopen("light.out","w",stdout); scanf("%d%d%d",&n,&Q,&num); REP(i,1,n-1){ int a,b; scanf("%d%d",&a,&b); E[a].push_back(b); E[b].push_back(a); } if(num>=11 && num<=13 || num>=17 && num<=18)p_list.solve(); else p100.solve(); return 0;}
小结:今天的题比较水,但是该ak的还是没有,切分还是不熟练吧(暴力敲太快了,cost打成to…)。
阅读全文
0 0
- 2017.10.15离线赛总结
- 2017.10.3离线赛总结
- 2017.10.4离线赛总结
- 2017.10.6离线赛总结
- 2017.10.7离线赛总结
- 2017.10.8离线赛总结
- 2017.10.9离线赛总结
- 2017.10.10离线赛总结
- 2017.10.11离线赛总结
- 2017.10.16离线赛总结
- 2017.10.17离线赛总结
- 2017.10.18离线赛总结
- 2017.10.19离线赛总结
- 2017.10.21离线赛总结
- 2017.10.24离线赛总结
- 2017.10.26离线赛总结
- 2017.10.27离线赛总结
- 2017.10.29离线赛总结
- C#图书管理系统完整源码
- Caffe初始数据可视化
- 第4章 烧写OpenWrt固件
- 初识多线程问题
- python 频率直方图
- 2017.10.15离线赛总结
- 日本某地发生了一件谋杀案,警察通过排查确定杀人凶手必为4个嫌疑犯 的一个。以下为4个嫌疑犯的供词。 A说:不是我。 B说:是C。 C说:是D。 D说:C在胡说 已知3个人说了真话,1个人说的是假话。
- jQuery 设计和自定义一个带展开动画效果的导航栏
- 模拟银行定期存款功能
- 第一周c++作业题解
- 使用Imagenet VGG-19模型进行图片识别
- 小白上github--关于导入github上的项目出现的问题及详解
- while循环输出学生成绩,平均分
- 第七周项目4