[NOIP补坑计划]NOIP2017 题解&做题心得
终于做完了……
场上预计得分:?(省一分数线:295)
由于看过部分题解所以没有预计得分qwq
题解:
D1T1 小凯的疑惑
震惊!一道小学奥数题竟难倒无数高中考生!
欢迎大家以各种姿势*和谐*出题人
证明见这篇博客
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<queue>
#include<map>
#define inf 2147483647
#define eps 1e-9
using namespace std;
typedef long long ll;
ll a,b;
int main(){
scanf("%lld%lld",&a,&b);
printf("%lld",a*b-a-b);
return ;
}
D1T2 时间复杂度
细节太多就不说了……我的代码应该是loj上最丑的
要特别注意的几个点:
1.不被执行的循环内可能会有语法错误;
2.要判断x=y=n的情况;
3.可能会开头没有F直接E;
4.看代码吧……
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<queue>
#include<stack>
#include<map>
#define inf 2147483647
#define eps 1e-9
using namespace std;
typedef long long ll;
int t,l,x,t1,t2,nd,las,cnt,mx,top,st[],nam[];
char s[];
bool ch,err,run,nm[],ntrun[];
int main(){
scanf("%d",&t);
while(t--){
memset(nm,,sizeof(nm));
memset(nam,,sizeof(nam));
memset(ntrun,,sizeof(ntrun));
err=ch=false;
run=true;
mx=t1=t2=x=top=cnt=;
las=-;
scanf("%d%s",&l,s+);
for(int i=,ii=strlen(s+);i<=ii;i++){
if(s[i]=='n')ch=true;
if(isdigit(s[i]))x=x*+s[i]-'';
}
if(x==&&!ch)nd=;
else nd=x;
for(int i=;i<=l;i++){
scanf("%s",s+);
if(s[]=='F'){
scanf("%s",s+);
if(!nm[s[]-'a'])nm[s[]-'a']=true,nam[i]=s[]-'a';
else err=true;
t1=t2=;
scanf("%s",s+);
if(s[]=='n')t1=;
else for(int i=;i<=strlen(s+);i++)t1=t1*+s[i]-'';
scanf("%s",s+);
if(s[]=='n')t2=;
else for(int i=;i<=strlen(s+);i++)t2=t2*+s[i]-'';
if((t1!=&&t2!=&&t1>t2)||(t1==&&t2<)){
if(run){
run=false;
las=i;
}
}
st[++top]=i;
if(run&&t1!=t2&&t2==)cnt++;
else ntrun[i]=true;
mx=max(mx,cnt);
}else{
if(top){
if(run&&!ntrun[st[top]])cnt--;
if(st[top]==las){
las=-;
run=true;
}
nm[nam[st[top]]]=false;
top--;
}else err=true;
}
}
if(top)err=true;
if(err)puts("ERR");
else puts(mx==nd?"Yes":"No");
}
return ;
}
D1T3 逛公园
听说SPFA会被卡?吓得我写了个dij……
显然是计数dp,设$dis[i]$表示i到终点的最短路,$f[i][k]$表示点i到终点距离小于等于$dis[i]+k$的方案数,记忆化搜索就好了……
如果一个状态同时出现多次则说明有零环无解;
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
#include<cmath>
#include<queue>
#include<stack>
#include<map>
#define inf 2147483647
#define eps 1e-9
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
struct edge{
int v,w,next;
}a[],_a[];
int t,n,m,k,p,u,v,w,tot=,_tot=,head[],_head[],f[][],dis[];
bool used[],ch[][];
void add(int u,int v,int w){
a[++tot].v=v;
a[tot].w=w;
a[tot].next=head[u];
head[u]=tot;
}
void _add(int u,int v,int w){
_a[++_tot].v=v;
_a[_tot].w=w;
_a[_tot].next=_head[u];
_head[u]=_tot;
}
void dij(int vs){
priority_queue<pii,vector<pii>,greater<pii> >q;
dis[vs]=;
q.push(pii(,vs));
while(!q.empty()){
int u=q.top().second;
q.pop();
if(used[u])continue;
used[u]=true;
for(int tmp=head[u];tmp!=-;tmp=a[tmp].next){
int v=a[tmp].v;
if(dis[v]>dis[u]+a[tmp].w){
dis[v]=dis[u]+a[tmp].w;
q.push(pii(dis[v],v));
}
}
}
}
int work(int x,int k){
if(ch[x][k])return -;
if(f[x][k])return f[x][k];
ch[x][k]=true;
if(x==n)f[x][k]=;
for(int tmp=_head[x];tmp!=-;tmp=_a[tmp].next){
int v=_a[tmp].v,nw=dis[v]-dis[x]+_a[tmp].w;
if(nw<=k){
int t=work(v,k-nw);
if(t==-)return f[x][k]=-;
f[x][k]=(f[x][k]+t)%p;
}
}
ch[x][k]=false;
return f[x][k];
}
int main(){
scanf("%d",&t);
while(t--){
tot=_tot=;
memset(used,,sizeof(used));
memset(f,,sizeof(f));
memset(ch,,sizeof(ch));
memset(head,-,sizeof(head));
memset(_head,-,sizeof(_head));
memset(dis,0x3f,sizeof(dis));
scanf("%d%d%d%d",&n,&m,&k,&p);
for(int i=;i<=m;i++){
scanf("%d%d%d",&u,&v,&w);
add(v,u,w);
_add(u,v,w);
}
dij(n);
printf("%d\n",work(,k)%p);
}
return ;
}
D2T1 奶酪
裸bfs水题送温暖~
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
#include<cmath>
#include<queue>
#include<stack>
#include<map>
#define inf 2147483647
#define eps 1e-9
using namespace std;
typedef long long ll;
struct edge{
ll v,next;
}a[];
ll t,n,h,r,tot=,x[],y[],z[],up[],dn[],head[];
bool ok,isin[];
void add(ll u,ll v){
a[++tot].v=v;
a[tot].next=head[u];
head[u]=tot;
}
bool bfs(){
queue<ll>q;
memset(isin,,sizeof(isin));
for(ll i=;i<=n;i++){
if(dn[i]){
q.push(i);
isin[i]=true;
}
}
while(!q.empty()){
ll u=q.front();
q.pop();
for(ll tmp=head[u];tmp!=-;tmp=a[tmp].next){
ll v=a[tmp].v;
if(up[v])return true;
if(!isin[v]){
q.push(v);
isin[v]=true;
}
}
}
return false;
}
int main(){
scanf("%lld",&t);
while(t--){
memset(head,-,sizeof(head));
memset(up,,sizeof(up));
memset(dn,,sizeof(dn));
tot=;
ok=false;
scanf("%lld%lld%lld",&n,&h,&r);
for(ll i=;i<=n;i++){
scanf("%lld%lld%lld",&x[i],&y[i],&z[i]);
if(z[i]<=r)dn[i]=true;
if(z[i]>=h-r)up[i]=true;
if(dn[i]&&up[i])ok=true;
}
if(ok){
puts("Yes");
continue;
}
for(ll i=;i<n;i++){
for(ll j=i+;j<=n;j++){
if((x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j])+(z[i]-z[j])*(z[i]-z[j])<=r*r*){
add(i,j);
add(j,i);
}
}
}
puts(bfs()?"Yes":"No");
}
return ;
}
D2T2 宝藏
看到数据范围肯定就是搜索或者状压DP了……听说记忆化搜索可以艹过去?
题解Orzxfz
设$f[i][s]$表示当前深度为i,已经访问过的点的状态为s,则$f[i][s]=min\{t∈s | f[i-1][t]+i*get(t,s\oplus t)\}$,其中$get(x,y)$表示集合y中所有点都向x中连边的最小代价;
枚举子集转移就好了,时间复杂度$O(n^23^n)$
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
#include<cmath>
#include<queue>
#include<stack>
#include<map>
#define inf 0x7f7f7f7f
#define eps 1e-9
#define lb(x) (x&-x)
using namespace std;
typedef long long ll;
ll n,m,ans=inf,u,v,w,d[][],f[][],lg[];
ll get(ll x,ll y){
ll ret=,tmp;
for(ll i=y;i;i-=lb(i)){
tmp=inf;
for(ll j=x;j;j-=lb(j)){
tmp=min(tmp,d[lg[lb(i)]][lg[lb(j)]]);
}
ret+=tmp;
}
return ret;
}
int main(){
memset(d,0x7f,sizeof(d));
memset(f,0x7f,sizeof(f));
for(int i=;i<=;i++)lg[<<i]=i;
scanf("%lld%lld",&n,&m);
for(ll i=;i<=m;i++){
scanf("%lld%lld%lld",&u,&v,&w);
u--,v--;
d[v][u]=d[u][v]=min(d[u][v],w);
}
if(n==)return puts(""),;
for(ll i=;i<n;i++){
f[][<<i]=;
}
for(ll i=;i<n;i++){
for(ll s=;s<(<<n);s++){
for(ll t=s;t;t=s&(t-)){
f[i][s]=min(f[i][s],f[i-][t]+i*get(t,s^t));
}
}
}
for(ll i=;i<n;i++){
ans=min(ans,f[i][(<<n)-]);
}
printf("%lld",ans);
return ;
}
D2T3 列队
这题标志着log级数据结构正式进入noip!(orzlxl)
splay的做法很明显……但是不好写并且€€£老爷机会卡常……
正解是对每一行和最后一列开一个线段树,每次$(x,y)$出队就找到第x行找到第y个未被使用的值(类似第k大),再从最后一列的那个线段树中找到第x个值放到第x行末尾,最后把开始找到的那个值放到最后一列末尾即可;
注意$y=m$时要特判,线段树要动态开点;
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
#include<cmath>
#include<queue>
#include<stack>
#include<map>
#define inf 0x7f7f7f7f
#define eps 1e-9
#define lb(x) (x&-x)
#define N 800000
using namespace std;
typedef long long ll;
struct node{
ll v;
int ls,rs;
}t[];
int n,m,q,x,y,cnt=,rts[];
vector<ll>v[];
void updata(int l,int r,int &u,int p){
if(!u)u=++cnt;
t[u].v++;
if(l==r)return;
int mid=(l+r)/;
if(p<=mid)updata(l,mid,t[u].ls,p);
else updata(mid+,r,t[u].rs,p);
}
int query(int l,int r,int u,int k){
if(l==r){
return l;
}
int mid=(l+r)/,tmp=mid-l+-t[t[u].ls].v;
if(tmp>=k)return query(l,mid,t[u].ls,k);
else return query(mid+,r,t[u].rs,k-tmp);
}
ll del1(int p,ll x){
ll ret;
int nw=query(,N,rts[n+],p);
updata(,N,rts[n+],nw);
if(nw<=n)ret=(ll)nw*m;
else ret=v[n+][nw-n-];
if(x)v[n+].push_back(x);
else v[n+].push_back(ret);
return ret;
}
ll del2(int p,int x){
ll ret;
int nw=query(,N,rts[p],x);
updata(,N,rts[p],nw);
if(nw<m)ret=(ll)(p-)*m+nw;
else ret=v[p][nw-m];
v[p].push_back(del1(p,ret));
return ret;
}
int main(){
scanf("%d%d%d",&n,&m,&q);
for(int i=;i<=q;i++){
scanf("%d%d",&x,&y);
printf("%lld\n",y==m?del1(x,):del2(x,y));
}
return ;
}
总结:
感觉14~17年难度在递增……这个D2T2和D2T3都好神仙啊qwq
NOIP2018 加油!!!!!
[NOIP补坑计划]NOIP2017 题解&做题心得的更多相关文章
- [NOIP补坑计划]NOIP2015 题解&做题心得
感觉从15年开始noip就变难了?(虽然自己都做出来了……) 场上预计得分:100+100+60~100+100+100+100=560~600(省一分数线365) 题解: D1T1 神奇的幻方 题面 ...
- [NOIP补坑计划]NOIP2012 题解&做题心得
场上预计得分:100+90+70+100+100+3060=490520(省一分数线245) 题解: D1T1 Vigenère 密码 题面 水题送温暖~~ #include<iostream& ...
- [NOIP补坑计划]NOIP2016 题解&做题心得
感觉16年好难啊QAQ,两天的T2T3是不是都放反了啊…… 场上预计得分:100+80+100+100+65+100=545(省一分数线280) ps:loj没有部分分,部分分见洛咕 题解: D1T1 ...
- [NOIP补坑计划]NOIP2013 题解&做题心得
场上预计得分:100+100+100+100+100+60=560(省一分数线410) 五道傻逼题+一道大搜索题…… 题解: D1T1 转圈游戏 题面 水题送温暖~ #include<algor ...
- [NOIP补坑计划]NOIP2014 题解&做题心得
六道普及组题,没啥好说的 场上预计得分:100+100+100+100+100+100=600(省一分数线490) (AK是不可能AK的,这辈子不可能AK的) 题解: D1T1 生活大爆炸版石头剪刀布 ...
- [BJOI2016]水晶 做题心得
[BJOI2016]水晶 做题心得 这是一个写了我两小时的傻逼题.写这个题浪费了一堆时间后,我才意识到我码力又不行了.于是整理起了实现技巧,开始练码力. 思路 不难.首先把 \((x,y,z)\) 变 ...
- CF1416D 做题心得
CF1416D 做题心得 上次在某trick中提到了这个题,一开始觉得太毒瘤没有写,现在把它补上了. 感觉实现这个东西,比单纯收获一个trick,收获的东西多太多了. 主要思路 它的主要trick是& ...
- [JSOI2019]节日庆典 做题心得
[JSOI2019]节日庆典 做题心得 一个性质有趣的字符串题 这要是在考场上我肯定做不出来吧 一开始还以为要 SAM 什么的暴力搞,没想到只用到了 \(Z\) 函数 -- 也是我生疏了罢 (学了啥忘 ...
- 2018.我的NOIP补全计划
code: efzoi.tk @ shleodai noip2011 D1 选择客栈 这道题是一道大水题,冷静分析一会就会发现我们需要维护最后一个不合法点和前缀和. 维护最后一个不合法点只要边扫描边维 ...
随机推荐
- Module.exports 和 exports
Module.exports 和 exports 在node中,没有全局作用域,只有模块作用域,外部访问不到内部,内部也访问不到外部,那么模块间如何通信 当加载一个模块的时候,被加载模块的代码在第一次 ...
- 使用IO,递归打印目录树
package chengbaoDemo; import java.io.File; import java.io.IOException; public class TestIOFile { pub ...
- js 文档加载完成之后执行 备用
//文档加载完成之后执行 (function(){ var _globeCallback; window.$$ = function(callback){ _globeCallback = callb ...
- Windows-命令窗口-强制关机命令
Windows +R CMD 命令行窗口shutdown -s -f -t 以上参数中的-s代表关机,-f表示强制关闭所有应用程序,-t 00代表不用等待立即执行(时间以秒计算,把时间改长就变成了定 ...
- SQL-Oracle-创建表空间,用户,授权
--创建表空间 create tablespace imark datafile 'E:\oracle\product\10.2.0\oradata\orcl\imark.dbf' size 500M ...
- IntelliJ IDEA 对于generated source的处理
IntelliJ IDEA 对于generated source的处理 学习了:https://stackoverflow.com/questions/5170620/unable-to-use-in ...
- Codeforces Round #234 (Div. 2) A. Inna and Choose Options
A. Inna and Choose Options time limit per test 1 second memory limit per test 256 megabytes input st ...
- mysql事务的开启
mysql事务的开启 对于一个MYSQL数据库(InnoDB),事务的开启与提交模式无非下面这两种情况: 1>若参数autocommit=0,事务则在用户本次对数据进行操作时自动开启,在用户执行 ...
- Centos6.5添加Epel和Remi源安装Lamp环境
想搭建一个Lamp环境,因为编译安装太麻烦,对于我这样的新手来说,太过于复杂.而CentOS自带的Apache.MySql和PHP的版本都太低,不想用.上百度搜了一轮,原来可以通过添加Epel和Rem ...
- 关于spring和extjs对接的过程简述
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http:// ...