NOIP 2017 全真模拟冲刺
---LRH&&XXY |
||||
题目名称 |
那些年 |
铁路计划 |
毁灭 |
|
题目类型 |
传统 |
传统 |
传统 |
|
可执行文件名 |
years |
trainfare |
destroy |
|
输入文件名 |
years.in |
trainfare.in |
destroy.in |
|
输出文件名 |
years.out |
trainfare.out |
destroy.out |
|
每个测试点时限 |
1.5s |
1.0s |
1.0s |
|
内存限制 |
256 MB |
256 MB |
256 MB |
|
测试点数目 |
20 |
20 |
20 |
|
每个测试点分值 |
5 |
5 |
5 |
40分
#include<iostream> #include<cstdio> #include<cstring> #define LL long long using namespace std; LL od,t; inline LL read(){ char ch=getchar();LL x=0,f=1; for(;!isdigit(ch);ch=getchar())if(ch==‘-‘)f=-1; for(;isdigit(ch);ch=getchar())x=x*10+ch-‘0‘; return x*f; } LL GCD(LL x,LL y){ return y==0?x:GCD(y,x%y); } LL gcd(LL a,LL b,LL &x,LL &y){ if(b==0){ x=1; y=0; return a; } LL r=gcd(b,a%b,x,y); LL tmp=0; tmp=x; x=y; y=(tmp-(a/b)*y); return r; } void slove1(){ t=read(); for(register LL i=1;i<=t;i++){ LL a,p,x,y; a=read();p=read(); LL r=gcd(a,p,x,y); while(x<0)x=p+x; printf("%I64d\n",x); } } void slove2(){ t=read(); for(register int i=1;i<=t;i++){ LL a,p; a=read();p=read(); printf("4\n1\n16\n6\n48\n"); } } void slove3(){ t=read(); for(register int i=1;i<=t;i++){ LL n,m,ans=0; n=read();m=read(); for(LL p=1;p<=n;p++) for(LL q=1;q<=m;q++) ans+=GCD(p,q); printf("%I64d\n",ans); } } void slove4(){ t=read(); for(register int i=1;i<=t;i++){ LL n,ans=0;n=read(); for(int j=1;j<=n;j++)ans+=n/j; printf("%I64d\n",ans); } } int main(){ freopen("years.in","r",stdin); freopen("years.out","w",stdout); od=read(); if(od==1)slove1(); if(od==2)slove2(); if(od==3)slove3(); if(od==4)slove4(); fclose(stdin);fclose(stdout); return 0; }
运输计划
【题目背景】
公元 2044 年,人类进入了宇宙纪元。
【题目描述】
L 国有 n 个星球,还有 m 条双向航道,每条航道建立在两个星球之间,这 m条航道连通了 L 国的所有星球。为了方便,我们规定1号星球为好星球。
在好星球上,小 P 掌管一家物流公司,该公司有m个运输计划。第i个运输计划形如:有一艘物流飞船需要从 ui 号星球飞行到相邻的vi 号星球去。对于航道 j,飞船驶过它所花费的时间为 tj。开始所有的tj都是1秒。但星球居民对运输计划极其不满。
为了鼓励科技创新,L 国国王允许小 P 使用魔法到某个运输计划上,飞船驶过被施魔法的航道消耗时间为2秒,一个运输计划最多只能被施加1次魔法,每年小p只能使用一次魔法。
由于居民不识数,改为2秒后他们感觉飞船跑得飕飕快,于是就可能会对好星球上的小p产生满意度。好星球每一年都会对居民进行一次满意度调查。如果一个星球上的居民到好星球的时间增加了,他们就会对小P的物流公司产生1点满意度。好星球上的居民永远不会对小p的物流公司产生满意度。
在计划实施前,你需要帮助小p的物流公司统计出未来的每一年中,各将有多少个星球的居民对好星球有满意度。
【输入描述】
第一行包含三个整数N、M、Q 分别表示宇宙中星球数,小P的运输计划数和运输计划将要实施的年数。
接下来M行,其中第i行包含两个整数ui,v1表示第i条航线链接ui和vi两个星球。
接下来Q行其中第j行包含一个整数Rj,表示计划实行后第j年将会对第Rj个运输计划施魔法。
【输出描述】
一共Q行 其中第j行表示第j年有多少星球的居民对好星球上小p的物流公司产生了满意度。
【数据范围及约定】
对于24%的数据,满足以下条件 N<=100 M<=4950 Q<=30
对于48%的测试数据 满足以下条件:Q<=30
对于另外 32%的测试数据,满足以下条件:正确输出中不同数字<=50种。
对于全部测试数据 满足以下条件:
2 <= N <= 100 000 , 1 <= Q <= M <= 200 000
1 <= ui ,vi <=N, ui、vi不相等 , 1 <= Rj <=M 。
题目大意:求每次将某条边+1后,有多少个点到1的最短路改变。
35分 q遍spfa
#include<iostream> #include<cstdio> #include<cstring> #include<queue> #include<algorithm> #define maxn 100005 using namespace std; queue<int>q; int n,m,qx,sumedge; int head[maxn],dis[maxn],g[maxn],inq[maxn]; inline int read(){ char ch=getchar();int x=0,f=1; for(;!isdigit(ch);ch=getchar())if(ch==‘-‘)f=-1; for(;isdigit(ch);ch=getchar())x=x*10+ch-‘0‘; return x*f; } struct Edge{ int x,y,z,nxt; Edge(int x=0,int y=0,int z=0,int nxt=0): x(x),y(y),z(z),nxt(nxt){} }edge[maxn<<2]; void add(int x,int y,int z){ edge[++sumedge]=Edge(x,y,z,head[x]); head[x]=sumedge; } inline void spfa(){ while(!q.empty())q.pop(); memset(dis,127/3,sizeof(dis)); memset(inq,0,sizeof(inq)); dis[1]=0;inq[1]=1;q.push(1); while(!q.empty()){ int now=q.front();q.pop();inq[now]=0; for(int i=head[now];i;i=edge[i].nxt){ int v=edge[i].y; if(dis[v]>dis[now]+edge[i].z){ dis[v]=dis[now]+edge[i].z; if(!inq[v]){ inq[v]=1; q.push(v); } } } } } int Spfa(){ while(!q.empty())q.pop(); memset(g,127/3,sizeof(g)); memset(inq,0,sizeof(inq)); g[1]=0;inq[1]=1;q.push(1); while(!q.empty()){ int now=q.front();q.pop();inq[now]=0; for(int i=head[now];i;i=edge[i].nxt){ int v=edge[i].y; if(g[v]>g[now]+edge[i].z){ g[v]=g[now]+edge[i].z; if(!inq[v]){ inq[v]=1; q.push(v); } } } } int js=0; for(register int i=1;i<=n;i++) if(dis[i]!=g[i])js++; return js; } int main(){ freopen("trainfare.in","r",stdin); freopen("trainfare.out","w",stdout); n=read();m=read();qx=read(); for(register int i=1;i<=m;i++){ int x,y; x=read();y=read(); add(x,y,1);add(y,x,1); } spfa(); for(register int i=1;i<=qx;i++){ int x;x=read(); edge[x*2].z++;edge[x*2-1].z++; printf("%d\n",Spfa()); } fclose(stdin);fclose(stdout); return 0; }
毁灭
【题目背景】
在神秘的玄灵大陆上生活着曲墨两个部族,他们世代对立。
曲族新任族长曲香檀为了壮大曲族,大开杀戮,纤纤素手,沾满鲜血。一日,她乔装遇刺,身负重伤。
墨族神医墨连城,被女子的美貌所吸引,不但救了她,两人同时坠入爱河。
曲香檀竭尽全力隐瞒身份,新谎言掩盖了旧谎言,最终仍误会成塔,她离开了他,继续她的杀戮,继续她的族长之路。
连城不忍心爱之人双手沾满献血,在曲香檀即将开展下一次杀戮时,他决定阻止她——破坏曲族内部联络通道,不惜代价......
【题目描述】
曲族在玄灵大陆有n个聚居地,当初曲香檀为了方便调配族人,在族人的聚居地之间开辟了许多双向空间隧道,保证任意两个聚居地可以直接或间接连通。同时为了节省资源对抗墨族,所以任意两个聚居地之间有且只有一条空间隧道可以直接或间接到达。现在为了抵御墨连城,曲香檀又耗费玄力,打通了m条双向地下暗河,但这m条暗河不能惠及每一个聚居地。曲族内部既可以通过空间隧道联络,也可以用地下暗河,当然也可以两者都用。
墨连城之前治疗曲香檀,耗费了大半玄力。又通过各种方法获取曲族新的联络网,玄力更是所剩无几。所以他决定仅破坏1条空间隧道和1条地下暗河。破坏后,只要曲族内部有任意2个聚居地不能互达,连城就成功了。想在,他想知道有多少种方式可以破坏曲族的内部联络。
【输入描述】
第一行包含两个整数n和m。
接下来n-1行,每行两个整数x,y,表示x和y之间有一条双向空间隧道。
接下来m行,每行两个整数x,y,表示x和y之间有一条双向地下暗河。
【输出描述】
一行表示答案
【样例输入1】
4 1
1 2
2 3
1 4
3 4
【样例输出1】
3
【注意】
样例2与样例3请看下发子文件夹
样例1解释:
地下暗河只有1条,3空间隧道任选一条都可以使曲族内部不连通,总共有3种方式
样例2与样例3不解释
【输出描述】
一行表示答案
【样例输入1】
4 1
1 2
2 3
1 4
3 4
【样例输出1】
3
【注意】
样例2与样例3请看下发子文件夹
样例1解释:
地下暗河只有1条,3空间隧道任选一条都可以使曲族内部不连通,总共有3种方式
样例2与样例3不解释
【子任务】
测试点编号 |
N= |
M= |
特殊性质 |
1 |
10 |
10 |
无 |
2 |
100 |
100 |
|
3、4 |
500 |
500 |
|
5、6、7 |
3000 |
3000 |
|
8、9、10 |
8000 |
1000 |
|
11 |
100000 |
50000 |
1、空间隧道构成一条链 2、每条地下暗河连通两个相邻聚居地 3、不会有两条地下暗河连通相同的聚居地 |
12 |
100000 |
70000 |
|
13 |
100000 |
90000 |
|
14、15、16 |
100000 |
100000 |
无 |
17、18、19、20 |
100000 |
1000000 |
题目大意:求切一条树边和非树边使图不连通有多少种方法
10分 md判断联通不连通应该用bfs...我这个傻叉用的kruskal....气哭...
#include<iostream> #include<cstdio> #include<cstring> using namespace std; int n,m,fa[100005]; long long ans; struct Edge{ int x,y,exit; }e[200008]; inline int read(){ char ch=getchar();int x=0,f=1; for(;!isdigit(ch);ch=getchar())if(ch==‘-‘)f=-1; for(;isdigit(ch);ch=getchar())x=x*10+ch-‘0‘; return x*f; } int f(int x){ return fa[x]==x?x:fa[x]=f(fa[x]); } bool cut(int p,int q){ int cnt=n; for(register int i=1;i<=n;i++)fa[i]=i; e[p].exit=0;e[q].exit=0; for(register int i=1;i<=n-1+m;i++){ if(e[i].exit==0)continue; int fx=f(e[i].x),fy=f(e[i].y); if(fx!=fy){ fa[fx]=fy; cnt--; } } e[p].exit=1;e[q].exit=1; return cnt!=1; } int main(){ freopen("destroy.in","r",stdin); freopen("destroy.out","w",stdout); n=read();m=read(); for(int i=1;i<n;i++){ e[i].x=read();e[i].y=read();e[i].exit=1; } int k=n-1; for(int i=1;i<=m;i++){ e[++k].x=read();e[k].y=read();e[k].exit=1; } for(int i=n;i<=m+n-1;i++) for(int j=1;j<n;j++) if(cut(i,j))++ans; printf("%I64d",ans); fclose(stdin);fclose(stdout); return 0; }