NOIP2012题解

Day1

Vigenère 密码 vigenere

直接模拟就好了,对于那张表找找规律就很短了。

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
#define MAX 1010
char k[MAX],c[MAX];
char get(char a,char b){return (((b-97)-(a-97)+26)%26)+97;}
int main()
{
scanf("%s",k);scanf("%s",c);
for(int i=0,l=strlen(c),lk=strlen(k);i<l;++i)
{
int x=0;
if(c[i]>='A'&&c[i]<='Z')c[i]+=32,x=-32;
if(k[i%lk]>='A'&&k[i%lk]<='Z')k[i%lk]+=32;
putchar(get(k[i%lk],c[i])+x);
}
puts("");return 0;
}

国王游戏 game

考虑两个人的先后顺序对于答案的影响。分类讨论之后不难发现每个人按照左手乘右手的值从小往大排序显然最优。高精度计算答案即可。

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<vector>
using namespace std;
#define ll long long
#define MAX 1050
inline int read()
{
int x=0;bool t=false;char ch=getchar();
while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
if(ch=='-')t=true,ch=getchar();
while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
return t?-x:x;
}
int n;
struct peo{int l,r;}p[MAX];
bool operator<(peo a,peo b){return 1ll*a.l*a.r<1ll*b.l*b.r;}
struct Bigint
{
int s[5000],ws;
void init(){s[ws=1]=1;}
void Multi(int b)
{
for(int i=1;i<=ws;++i)s[i]*=b;
for(int i=1;i<=ws;++i)s[i+1]+=s[i]/10,s[i]%=10;
while(s[ws+1])++ws,s[ws+1]+=s[ws]/10,s[ws]%=10;
}
void output(){for(int i=ws;i;--i)printf("%d",s[i]);puts("");}
}ans,now;
bool operator<(Bigint a,Bigint b)
{
if(a.ws!=b.ws)return a.ws<b.ws;
for(int i=a.ws;i;--i)
if(a.s[i]!=b.s[i])return a.s[i]<b.s[i];
return false;
}
Bigint operator/(Bigint a,int b)
{
int r=0;
for(int i=a.ws;i;--i)
{
r=r*10+a.s[i];
a.s[i]=r/b;r%=b;
}
while(a.ws>1&&!a.s[a.ws])--a.ws;
return a;
}
int main()
{
n=read();now.init();now.Multi(read());read();
for(int i=1;i<=n;++i)p[i].l=read(),p[i].r=read();
sort(&p[1],&p[n+1]);
for(int i=1;i<=n;++i)
{
ans=max(ans,now/p[i].r);
now.Multi(p[i].l);
}
ans.output();
return 0;
}

开车旅行 drive

好题。

预处理出在每个位置\(A\)和\(B\)分别会走到哪里,可以用链表实现。接下来把\(A,B\)分别走一次看做一组,直接倍增求解即可。注意最后\(A\)还可能可以单独走一次。

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<vector>
using namespace std;
#define ll long long
#define MAX 100100
inline int read()
{
int x=0;bool t=false;char ch=getchar();
while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
if(ch=='-')t=true,ch=getchar();
while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
return t?-x:x;
}
int n;
int h[MAX];
int dA[MAX],dB[MAX];
namespace Destination
{
int nt[MAX],lt[MAX],p[MAX],id[MAX];
bool cmp(int a,int b){return h[a]<h[b];}
void upd(int &mx,int &mxx,int i,int j)
{
int s=abs(h[i]-h[j]);if(!j)return;
if(!mx||s<abs(h[i]-h[mx])||(s==abs(h[i]-h[mx])&&h[j]<h[mx]))swap(mx,mxx),mx=j;
else if(!mxx||s<abs(h[i]-h[mxx])||(s==abs(h[i]-h[mxx])&&h[j]<h[mxx]))mxx=j;
}
void Work()
{
for(int i=1;i<=n;++i)p[i]=i;
sort(&p[1],&p[n+1],cmp);
for(int i=1;i<=n;++i)lt[p[i]]=p[i-1],nt[p[i]]=p[i+1];
for(int i=1;i<=n;++i)
{
int mx=0,mxx=0;
upd(mx,mxx,i,lt[i]);upd(mx,mxx,i,lt[lt[i]]);
upd(mx,mxx,i,nt[i]);upd(mx,mxx,i,nt[nt[i]]);
nt[lt[i]]=nt[i];lt[nt[i]]=lt[i];lt[0]=nt[0]=0;
dA[i]=mxx;dB[i]=mx;
}
}
}
int p[17][MAX],sA[17][MAX],sB[17][MAX];
void Query(int S,int X,int &disA,int &disB)
{
disA=disB=0;
for(int i=16;~i;--i)
if(p[i][S]&&X>=sA[i][S]+sB[i][S])
disA+=sA[i][S],disB+=sB[i][S],X-=sA[i][S]+sB[i][S],S=p[i][S];
if(dA[S]&&X>=abs(h[S]-h[dA[S]]))
disA+=abs(h[S]-h[dA[S]]);
}
int main()
{
n=read();
for(int i=1;i<=n;++i)h[i]=read();
Destination::Work();
for(int i=1;i<=n;++i)
{
p[0][i]=dB[dA[i]];
sA[0][i]=abs(h[i]-h[dA[i]]);
sB[0][i]=abs(h[dA[i]]-h[dB[dA[i]]]);
}
for(int i=1;i<17;++i)
for(int j=1;j<=n;++j)
{
p[i][j]=p[i-1][p[i-1][j]];
sA[i][j]=sA[i-1][j]+sA[i-1][p[i-1][j]];
sB[i][j]=sB[i-1][j]+sB[i-1][p[i-1][j]];
}
int X=read();double Rate=1e18;int pos=0;
for(int i=1;i<=n;++i)
{
int disA,disB;double V=0;
Query(i,X,disA,disB);
if(!disB)V=1e18-1;
else V=1.0*disA/disB;
if(V<Rate)Rate=V,pos=i;
else if(V==Rate&&h[i]>h[pos])pos=i;
}
printf("%d\n",pos);
int Q=read();
while(Q--)
{
int S=read(),X=read(),disA,disB;
Query(S,X,disA,disB);
printf("%d %d\n",disA,disB);
}
return 0;
}

Day2

同余方程 mod

\(exgcd\)模板题

#include<iostream>
using namespace std;
int a,b;
void exgcd(int a,int b,int &x,int &y){if(a==0){x=0;y=1;return;}exgcd(b%a,a,y,x);x-=b/a*y;}
int inv(int a,int b){int x,y;exgcd(a,b,x,y);x=(x%b+b)%b;return x;}
int main()
{
cin>>a>>b;
cout<<inv(a,b)<<endl;
return 0;
}

借教室 classroom

二分答案,差分\(check\)。

#include<iostream>
#include<cstdio>
using namespace std;
#define MAX 1000100
inline int read()
{
int x=0;bool t=false;char ch=getchar();
while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
if(ch=='-')t=true,ch=getchar();
while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
return t?-x:x;
}
int n,m,s[MAX],d[MAX],l[MAX],r[MAX],a[MAX];
bool check(int k)
{
for(int i=1;i<=n;++i)a[i]=0;
for(int i=1;i<=k;++i)a[l[i]]+=d[i],a[r[i]+1]-=d[i];
for(int i=1;i<=n;++i){a[i]+=a[i-1];if(a[i]>s[i])return false;}
return true;
}
int main()
{
n=read();m=read();
for(int i=1;i<=n;++i)s[i]=read();
for(int i=1;i<=m;++i)d[i]=read(),l[i]=read(),r[i]=read();
int l=1,r=m,ret=m+1;
while(l<=r)
{
int mid=(l+r)>>1;
if(check(mid))l=mid+1;
else ret=mid,r=mid-1;
}
if(ret>m)puts("0");else printf("-1\n%d\n",ret);
return 0;
}

疫情控制 blockade

好题。

不难发现可以二分答案。考虑如何\(check\)。

首先如果一支军队不能走到根节点那么显然它就停在能够到达的深度最浅的位置一定最优。那么军队分为两类,一类可以到达根节点,即可以控制其他子树,另外一类则不行,那么停留在最优位置不动。接下来,先不考虑可以控制其他子树的军队,\(dfs\)一遍,看看哪些子树需要控制。显然控制在根节点的儿子位置一定最优。显然所有可以控制其他子树的军队全部到达根节点,然后按照剩余移动时间排序。所有需要被覆盖的子树按照距离排序。从小往大一一匹配即可。注意一个问题,考虑一支军队的时候,如果它过来的那个子树还未被覆盖,那么优先覆盖他过来的那棵子树。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define ll long long
#define MAX 50050
inline int read()
{
int x=0;bool t=false;char ch=getchar();
while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
if(ch=='-')t=true,ch=getchar();
while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
return t?-x:x;
}
struct Line{int v,next,w;}e[MAX<<1];
int h[MAX],cnt=1;
inline void Add(int u,int v,int w){e[cnt]=(Line){v,h[u],w};h[u]=cnt++;}
int n,m,top[MAX],a[MAX];
ll s[16][MAX],dep[MAX];
int p[16][MAX];
void dfs(int u,int ff)
{
dep[u]=dep[ff]+s[0][u];
for(int i=1;i<16;++i)
p[i][u]=p[i-1][p[i-1][u]],s[i][u]=s[i-1][u]+s[i-1][p[i-1][u]];
for(int i=h[u];i;i=e[i].next)
if(e[i].v!=ff)
p[0][e[i].v]=u,s[0][e[i].v]=e[i].w,dfs(e[i].v,u);
}
void dfs(int u,int ff,int id)
{
top[u]=id;
for(int i=h[u];i;i=e[i].next)
if(e[i].v!=ff)dfs(e[i].v,u,id);
}
int Move(int u,ll x)
{
for(int i=15;~i;--i)
if(p[i][u]&&x>=s[i][u])
x-=s[i][u],u=p[i][u];
return u;
}
struct Army{int fr;ll t;}q[MAX];
bool operator<(Army a,Army b){return a.t<b.t;}
bool cmp(int a,int b){return dep[a]<dep[b];}
bool vis[MAX];
void dfs2(int u,int ff)
{
bool fl=true;int son=0;
for(int i=h[u];i;i=e[i].next)
if(e[i].v!=ff)
{
dfs2(e[i].v,u);++son;
if(!vis[e[i].v])fl=false;
}
if(fl&&son)vis[u]=true;
}
int nd[MAX];
bool check(ll t)
{
int tot=0,sum=0;memset(vis,0,sizeof(vis));
for(int i=1;i<=m;++i)
{
int x=Move(a[i],t);
if(x==1)q[++tot]=(Army){top[a[i]],t-dep[a[i]]};
else vis[x]=true;
}
dfs2(1,0);if(vis[1])return true;
for(int i=h[1];i;i=e[i].next)
if(!vis[e[i].v])nd[++sum]=e[i].v;
sort(&q[1],&q[tot+1]);
sort(&nd[1],&nd[sum+1],cmp);
if(tot<sum)return false;int j=1;
for(int i=1;i<=tot;++i)
{
if(!vis[q[i].fr]){vis[q[i].fr]=true;continue;}
while(j<=sum&&vis[nd[j]])++j;
if(q[i].t>=dep[nd[j]])vis[nd[j]]=true;
}
while(j<=sum&&vis[nd[j]])++j;
return j>sum;
}
int main()
{
n=read();
for(int i=1;i<n;++i)
{
int u=read(),v=read(),w=read();
Add(u,v,w);Add(v,u,w);
}
dfs(1,0);
for(int i=h[1];i;i=e[i].next)dfs(e[i].v,1,e[i].v);
m=read();
for(int i=1;i<=m;++i)a[i]=read();
ll l=0,r=5e13,ret=-1;
while(l<=r)
{
ll mid=(l+r)>>1;
if(check(mid))ret=mid,r=mid-1;
else l=mid+1;
}
printf("%lld\n",ret);
return 0;
}

NOIP2012题解的更多相关文章

  1. NOIP2012 题解

    Vigenère 密码 这个名字实在打不来... 题解:模拟 #include <cstdio> #include <cstring> +; bool cj; int cl, ...

  2. [NOIP补坑计划]NOIP2012 题解&做题心得

    场上预计得分:100+90+70+100+100+3060=490520(省一分数线245) 题解: D1T1 Vigenère 密码 题面 水题送温暖~~ #include<iostream& ...

  3. NOIP2012 疫情控制 题解(LuoguP1084)

    NOIP2012 疫情控制 题解(LuoguP1084) 不难发现,如果一个点向上移动一定能控制更多的点,所以可以二分时间,判断是否可行. 但根节点不能不能控制,存在以当前时间可以走到根节点的点,可使 ...

  4. [NOIP2012提高]借教室 题解(二分答案+差分)

    [NOIP2012提高&洛谷P1083]借教室 Description 在大学期间,经常需要租借教室.大到院系举办活动,小到学习小组自习讨论,都需要向学校申请借教室.教室的大小功能不同,借教室 ...

  5. noip2012开车旅行 题解

    题目大意: 给出n个排成一行的城市,每个城市有一个不同的海拔.定义两个城市间的距离等于他们的高度差的绝对值,且绝对值相等的时候海拔低的距离近.有两个人轮流开车,从左往右走.A每次都选最近的,B每次都选 ...

  6. [NOIP2012]国王游戏 题解

    题目大意: n个人排成一排,排头固定,其他可以变.每一个人左右手都有一个整数,一个人的分数为他所有前面的人左手上的数的乘积除以他右手上的数(向下取整),求在整列中最大分数的最小值. 思路: 首先,一切 ...

  7. [NOIP2012]借教室 题解

    题目大意: 有一个n个数的数列,m个操作,第i个操作使[li,ri]区间建di,问第几个操作使数列中出现负数. 思路: 暴力显然过不了,那么就可以优化了,不难想到线段树,显然需要良好的姿势,那么就差分 ...

  8. 【数学】【NOIp2012】同余方程 题解 以及 关于扩展欧几里得与同余方程

    什么是GCD? GCD是最大公约数的简称(当然理解为我们伟大的党也未尝不可).在开头,我们先下几个定义: ①a|b表示a能整除b(a是b的约数) ②a mod b表示a-[a/b]b([a/b]在Pa ...

  9. 【NOIP2012】DAY1+DAY2题解

    不贴代码的原因是我的代码在初中机房.忘记带过来了. DAY 1 T1随便搞,但是字符串相关的题我经常犯蠢 T2 一个结论题,OAO但是需要高精度写. 具体就是按左手的数除右手的数(还是怎么的来着)排个 ...

随机推荐

  1. NOIp2014提高组初赛错题简析

    总体分析 \(89pts\),粗略来看选择题错的比较多,\(-6pts\).同时又是尿性的填空杀扣了\(5pts\). 不过后面的两大题全对了还是可喜可贺 错题精析 单项选择T8 编译器的主要功能是( ...

  2. 电脑一直报PCIE BUS错误的原因

    报错 新装Linux 系统后,每隔数分钟则报以下错误: AER:Corrected error received: 0000:00:1c:4 pcie bus error: severity=Corr ...

  3. aurora 64B/66B ip核设置与例程代码详解

    见网页https://blog.csdn.net/u014586651/article/details/84349328 https://blog.csdn.net/u012135070/articl ...

  4. Ubuntu16.04下安装QQ的完整操作记录(经验证可用)

    本机安装了Ubuntu16.04系统,用于日常运维办公.打算在Ubuntu上安装QQ,如下操作记录也使用于Ubuntu18.04: 1)先下载特制的QQ程序包(其实就是基于Wine容器做了一些封装,程 ...

  5. Daily Scrum NO.10

    工作概况 今天是两周正是开发的最后一个工作日,虽然也是编译的DEADLINE,但成员们还是较为积极.计划内的工作基本都能够完成:线程池.异常清理器和动态爬取的功能.异常清理器界面的第一版也在今晚做了出 ...

  6. 软件工程个人项目作业 Individual Project

    利用Junit4进行程序模块的测试,回归测试 源码 https://github.com/dpch16303/test/blob/master/%E5%9B%9E%E5%BD%92%E6%B5%8B% ...

  7. POI (Apache POI)

    Apache POI是Apache软件基金会的开放源码函式库,POI提供API给Java程序对Microsoft Office格式档案读和写的功能. 基本功能 编辑 结构: HSSF - 提供读写Mi ...

  8. [2017BUAA软工]个人项目:数独

    一.项目地址 https://github.com/Slontia/Sudoku 附加作业(GUI):https://github.com/Slontia/SudokuGUI 二.开发时间 PSP2. ...

  9. org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'stu' defined in class path resource [applicationContext.xml]: Instantiation of bean failed; nested exception is

    org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'stu' defined ...

  10. Activiti解析.bpmn文件获得User Task节点的CandidateUsers特性的值

    参考文档: http://www.cnblogs.com/mingforyou/p/5351332.html http://blog.csdn.net/jackyrongvip/article/det ...