1. 程式人生 > >NOIP2017遊記+題解+標程

NOIP2017遊記+題解+標程

文章目錄


洛谷題目連結
題解和標程在後面(是在day20的後面,day1和day2裡面的是遊記不是題解!)
因為今年題目難度和風格太不友善,就不每一題分別寫題解了
除了d2t3佇列,點選進入

Day0

結束了三週的停課訓練(其實不想結束)
回家休息一下(猩球大戰3挺好看的)
晚上去廣州
這次不在六中比賽,換到了二中
區別在於,六中可以在考場的窗外看到廣州塔,二中外面全是山
二中在蘿崗區,是個新區,新到晚上想出去玩,都只有一個地方可以去,摩拜也找不到,路燈什麼的都沒裝。
趁著酒店搞消防演習停電,找到理由去萬達走了一圈

Day1

這床好舒服啊
畢竟是四星級酒店
早餐也很不錯,基本上想得到的都有

提前十五分鐘進考場,轉了幾圈,沒有我的位置?
直到快開始才給了我一個備用機
然後我驚奇的發現,我的備用機是win7,6代i5,8G,其他人的都是XP!!
rp++
然後不給試機?
那提前有什麼用?

開始看第一題
啊!!!NOIPD1t1考數論??
然後我在草稿紙上寫了ax+by=c
然後懵逼了好一會
算了先過

第二題是迴圈模擬,不久前做過一道題,那個要算具體迴圈次數,這題還是很簡單的,秒掉

再看第三題
要求路程少於一個距離的路徑數量
又懵逼了許久
然後猛然發現他的k只有50,意思就是最多求比最短路長50的路
那直接拆點不就行了嗎?
切掉

回去看第一題
又看了許久,已經9:10了
我不敢再看了,趕緊打了個暴力,順便找一下規律
打了個表,好像很有規律啊
然後仔細看了看,不就是n*m-n-m嗎?
於是用暴力驗證這個規律
好像是對的,那第一題意外切掉

去打第二題,c++字串處理比較麻煩,除錯也花了一點時間,但在10:10之前,大樣例也過了

第三題先碼了個spfa
然後複製一遍,加上k這個限制
測試樣例,錯了
接著我發現這種做法好像有錯誤,在累加方案的時候可能會算重
怎麼辦??先上個廁所冷靜一下
回來之後發現拓撲排序一下就好了
迅速加上拓撲排序(說是迅速,打完已經十一點了)
調過小樣例,又花了十分鐘
試大樣例,沒過!!
但是我不會打暴力,也沒時間拍
肉眼查錯
查出一堆小錯,改掉
過大樣例了!!
11:50了!!
然而我還沒有判無解
保險起見,先放著,把前兩題再肉眼一遍,再試一遍有沒有錯
把提交的資料夾建好,各種操作處理完,已經沒時間了
第三題只有70分,被卡成暴力分,AK失敗
估分100+100+70

出考場後問大家,發現前兩題都穩穩的,第三題大多都有70分
除了某些人有點小爆炸
聽說一數論大佬推第一題推了半個鍾,用上了各種高階玩意,還弄錯了?

午餐在二中飯堂吃
紀中飯堂最爛定律還未被打破
吃飯時毫無疑問的在討論問題
然後突然發現我第二題有一個bug
對於已經判斷是ERR的,剩下的我直接用
scanf("%s\n",s);
處理掉
然後聽說這樣會讀到空格就停止?
有大佬知道會不會的一定要告訴我
那我不就慘了?又被卡掉30分?只剩240了?
鬱悶

中午回去,睡的挺舒服
下午騎車出去浪,發現新區人少,空氣好,公園全鋪了綠道,可以說是廣州的世外桃源了
晚飯回二中飯堂,於是就發生了初中生大量請假不跟隊去飯堂的事
聽說他們會被處理
晚上又去萬達(就這一個地方可以去)

其實day1結束後不久,各個Q群上就有各種評論了
UOJ群上的評論有一個很亮
NOIP奇數年必出神搜尋題
NOIP2013mayan遊戲
NOIP2015鬥地主
包括什麼靶形數獨都在NOIP奇數年
立了個大flag

#Day2
和day1一樣,早餐很好,睡的很好
早上一個趣事
在酒店自助餐廳吃飯,因為不給試機,就不去那麼早,在餐廳坐著和咖啡。突然老師站起來,拍了下手,說走了出發了。於是餐廳裡絕大多數人站了起來,湧了出去,餐廳幾乎空了……

還是沒有我的位置,坐回備用機
看題第一眼
首先看到的是第一題上那個計算公式
woc,d1t1數論,d2t1立體幾何??
然後仔細看了看
額這不就是聯通塊嗎
n才1000,那不隨便做嗎,切掉

t2,看題感覺是最小生成樹之類的
然後懵逼了幾分鐘
突然看到n才12
那不提示狀壓嗎,狀壓很可做啊
我隨手設了一個到x層,選取狀態為s
然後就不會了,因為我不知道接下來怎麼轉移
很快,我想到了應該再列舉新一輪選取的點的狀態,但是這些點和哪些點連,我還是不知道怎麼做
於是狀態加設一維:表示第x層選的是哪些點,預處理一下
好像可以切,先過

看t3
flag果然沒破
應該是什麼資料結構之類的
但是我只想到了直接模擬,還有n=1的splay
想到9點,無果
算了先打第一題

第一題十分鐘打完,很順利,樣例幾乎一遍過
打t2,因為考慮還算充分,邊打邊稍微修改了一下想法,10點左右打完
調過大樣例後,試了一下極限
跑3s,好像有希望
算了一下空間,700M,希望破滅
把陣列開到適應n=11,空間變成100M
時間是秒過
然後思考了一下70分之後有多少分
覺得大概80分
思考了好久怎麼去掉一個狀態
思考不到
那就先放著,去搞第三題

第三題很快打完模擬,隨後發現並不需要模擬整個陣列,僅需對操作模擬就行了
這樣是q方的,q只有500,可以過50分
11點左右,看還有時間,就打了個splay,再騙20分
到了11:30,先去看了看前兩題還有什麼問題,順便想一想第二題可不可以去掉一個狀態
還是無果
第三題又不停的想水法,然而只能常數優化,沒有作用,在n為10的5次方時應該沒有作用

那麼估分100+70~80+70

中午吃飯的時候討論了一下,猛然發現自己真傻
第二題我的第二個二進位制狀態沒有任何作用,列舉新選哪些點後可以直接連到最深一層,因為連到前面如果更優會在轉移到這一層之前就考慮到

第三題howarli給了一種做法:
對於每一行維護一個splay,對於最後一列維護一個splay,當然不用全部維護,僅維護成為答案的點,這個再用主席樹維護
說起來簡單,打起來可不是NOIP風格

聽說alanAK了(不過也正常,這麼NOIP的題)??%%%

#問題
碼力不足,調程式速度過慢
雖說有機器的原因,但主要原因還是自己平時訓練不足

數學不行(雖然在這次沒有體現出來),D1t1lyd大佬1分鐘切掉

對模型和一些方法的掌握和運用不到位
D2t2很裸的狀壓DP都沒有切掉,甚至想到了正確的狀態設定也沒有想到正解,強行把正解變成暴力

不能掉以輕心,要求穩
D1t2可能會因為使用了那種輸入而被卡掉
…………

Day3

由停課訓練變為停訓補課,昏昏沉沉,面前堆著兩個星期的作業

Day4

等待成績和程式碼中

Day8

學軍資料早就出來了,得分是440,d2t1因為longlong卡掉20分等
那個scanf真的會炸啊!!!

這裡寫圖片描述
這個是GGF,不是CCF,CCF一點都不騙錢對吧

這裡寫圖片描述

Day10

成績已出,有點爆炸,離我的估分和學軍資料都有點距離
然而是反向爆炸?
100+90+60+100+75+70
那個scanf只爆了10分?

還有一個,noi官網出成績時間推遲兩次是什麼情況

Day20

分數線已出,廣東295,最高浙江,360
這次怎麼差了這麼多?

題解

d1t1

輸入n,m,輸出n*m-n-m
可以打表證明
具體證明我可以大概弄出來,但是真的講不出來(太弱了)

d1t2

直接模擬即可
用遞迴,打個棧之類的都行

d1t3

最短路求方案數大家肯定會
那麼設f[i][j]為到點i,比最短路長j的方案數
先求出一個最短路,然後拓撲排序做
求拓撲序是加一個優化:對於沒用的點,直接刪掉
設這個點是(i,j),如果起點到i的最短路+j+i到終點的最短路已經大於k,就刪掉它
加上這個優化9s變2s

d2t1

直接列舉任意兩點是否可以連通,直接做最短路即可
如果卡longlong,可以用unsigned long long

d2t2

狀壓DP
設f[x][s]表示到最深第x層,選取了點的狀態為s1
在上面已經大概講過了,再重複一遍
每次選取一個s的補集s1,並選取這些點
設c[s][s1]表示有s這些點,要連通s1這些點,選取的邊的和的最小值
那麼轉移f[x+1][s+s1]=f[x][s]+c[s][s1]xf[x+1][s+s1]=f[x][s]+c[s][s1]*x
因為如果連到比x深度更淺的點更優,會在之前被考慮

程式

d1t1

#include<cstdio>
#include<algorithm>
#include<cstring>
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define fd(i,a,b) for(int i=a;i>=b;i--)
#define ll long long
using namespace std;
ll x,y;
int main()
{
	freopen("math.in","r",stdin);
	freopen("math.out","w",stdout);
	scanf("%lld%lld",&x,&y);
	printf("%lld\n",x*y-x-y);
	fclose(stdin);fclose(stdout);
	return 0;
}

d1t2

#include<cstdio>
#include<algorithm>
#include<cstring>
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define N 110
using namespace std;
int n,m,i=1,ans=0,flag=1,bz[N+N];
char s[N];
int get()
{
	char c=getchar();int x=0;
	if(c=='n') 
	{
		getchar();
		return -1;
	}
	for(;c>='0'&&c<='9';c=getchar()) x=x*10+c-48;
	return x;
}
void dg(int x)
{
	int aans=ans,hy=ans;
	while(i<=n)
	{
		i++;
		char c=getchar();
		if(c=='E')
		{
			scanf("\n");
			ans=aans;
			return;
		}
		scanf(" %c ",&c);
		if(bz[c]==1) flag=0;
		bz[c]=1;
		int q=get(),w=get();
		if(q==-1&&w==-1)
		{
			dg(x+1);
		}
		if(q==-1&&w>0)
		{
			int jy=ans;dg(x+1);
			ans=jy;
		}
		if(q>0&&w==-1)
		{
			ans++;dg(x+1);
		}
		if(q>0&&w>0)
		{
			int jy=-1;
			if(q>w) jy=ans;dg(x+1);
			if(jy!=-1) ans=jy;
		}
		bz[c]=0;
		aans=max(ans,aans);
		ans=hy;
	}
	ans=aans;
	if(i>n&&x!=0) flag=0;
}
int main()
{
	freopen("complexity.in","r",stdin);
	freopen("complexity.out","w",stdout);
	int ac;scanf("%d\n",&ac);
	for(;ac;ac--)
	{
		memset(bz,0,sizeof(bz));
		i=1;flag=1;ans=0;
		char c;scanf("%d O(%c",&n,&c);
		if(c=='n')
		{
			scanf("^%d",&m);
		}
		else m=0;
		scanf(")\n");
		dg(0);
		if(i<=n) 
		{
			flag=0;
			while(i<=n)
			{
				char c=getchar();
				if(c=='E')
				{
					scanf("\n");
				}
				else
				{
					scanf(" %c ",&c);
					int q=get();q=get();
				}
				i++;
			}
		}
		if(flag==0) printf("ERR");
		else
		{
			if(ans==m) printf("Yes");
			else printf("No");
		}
		printf("\n");
	}
	fclose(stdin);fclose(stdout);
	return 0;
}

d1t3

#include<cstdio>
#include<algorithm>
#include<cstring>
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define N 111000
#define cl(a) memset(a,0,sizeof(a))
#define ll long long
using namespace std;
int n,m,k,mo,last[N],next[N*2],to[N*2],date[N*2],tot=0,g[N],d[N*100][2],bz[N],flag=0,g1[N];
int las[N*50],nex[N*100],tt[N*100],data[N*100],rd[N*60],d1[N*60],bz1[N][52],q[N*10][3],mm;
int xhcs;
ll f[N*60];
void putin(int x,int y,int z)
{
    next[++tot]=last[x];last[x]=tot;to[tot]=y;date[tot]=z;
}
void put(int x,int y,int z)
{
    nex[++tot]=las[x];las[x]=tot;tt[tot]=y;data[tot]=z;rd[y]++;
}
void SPFA(int S)
{
    int he=0,ta=1;
    d[1][0]=S;bz[S]=1;
    memset(g,60,sizeof(g));
    g[S]=0;
    while(he<ta)
    {
        int x=d[++he][0];
        for(int i=last[x];i;i=next[i])
        {
            int y=to[i];
            if(g[x]+date[i]<g[y])
            {
                g[y]=g[x]+date[i];
                if(bz[y]==0) bz[y]=1,d[++ta][0]=y;
            }
        }
        bz[x]=0;
    }
}
void bfs()
{
    mm=0;
    cl(bz1);
    int he=0,ta=1;
    d[1][0]=bz1[1][0]=1;
    d[1][1]=0;
    while(he<ta)
    {
        int x=d[++he][0],z=d[he][1];
        for(int i=last[x];i;i=next[i])
        {
            int y=to[i],q=g[x]+z+date[i]-g[y];
            if(q<=k&&g[y]+q+g1[y]-g[n]<=k)
            {
                put(z*n+x,q*n+y,date[i]);
                if(bz1[y][q]==0) bz1[y][q]=1,d[++ta][0]=y,d[ta][1]=q,mm++;
            }
        }
    }
    he=0;
}
void gans()
{
    int he=0,ta=0;
    fo(i,1,mm) if(rd[i]==0) d1[++ta]=i;
    f[1]=1;
    while(he<ta)
    {
        int x=d1[++he];
        f[x]%=mo;
        for(int i=las[x];i;i=nex[i])
        {
            int y=tt[i];
            f[y]+=f[x];
            rd[y]--;
            if(rd[y]==0) d1[++ta]=y;
        }
    }
    if(ta<mm) f[0]=-1;
}
int main()
{
    freopen("park.in","r",stdin);
   // freopen("park.out","w",stdout);
    int ac;scanf("%d",&ac);
    for(;ac;ac--)
    {
        scanf("%d%d%d%d",&n,&m,&k,&mo);
        cl(last);tot=0;
        fo(i,1,m)
        {
            scanf("%d%d%d",&q[i][0],&q[i][1],&q[i][2]);
            putin(q[i][1],q[i][0],q[i][2]);
        }
        SPFA(n);
        fo(i,1,n) g1[i]=g[i];
        cl(last);tot=0;
        fo(i,1,m) putin(q[i][0],q[i][1],q[i][2]);
        SPFA(1);
        tot=0;
        cl(las);cl(rd);
        xhcs=0;
        bfs();
        cl(f);
        gans();
        int ans=0;
        if(f[0]==-1) printf("-1\n");
        else
        {
            fo(j,0,k) (ans+=f[j*n+n])%=mo;
            printf("%d\n",ans);
        }
    }
}

d2t1

#include<cstdio>
#include<cstring>
#include<algorithm>
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define N 1010
#define ll long long
#define ull unsigned long long
using namespace std;
int n,b[N][N],d[N],bz[N];
ll h,r,a[N][3];
void read(ll &x)
{
	char c=getchar();ll y=1;x=0;
	for(;c<'0'||c>'9';c=getchar()) if(c=='-') y=-1;
	for(;c>='0'&&c<='9';c=getchar()) x=x*10+c-48;
	x*=y;
}
ll sqr(ll x){return x*x;}
ull dis(int x,int y)
{
	return sqr(a[x][0]-a[y][0])+sqr(a[x][1]-a[y][1])+sqr(a[x][2]-a[y][2]);
}
void bfs()
{
	d[1]=n+1;memset(bz,0,sizeof(bz));
	int he=0,ta=1;bz[n+1]=1;
	while(he<ta)
	{
		if(bz[n+2]) break;
		int x=d[++he];
		fo(j,1,n+2) if(b[x][j]&&!bz[j]) bz[j]=1,d[++ta]=j;
	}
}
int main()
{
	freopen("cheese.in","r",stdin);
	freopen("cheese.out","w",stdout);
	int ac;scanf("%d",&ac);
	for(;ac;ac--)
	{
		scanf("%d",&n);read(h);read(r);
		fo(i,1,n) read(a[i][0]),read(a[i][1]),read(a[i][2]);
		memset(b,0,sizeof(b));
		fo(i,1,n)
		{
			fo(j,i+1,n)
			{
				if(dis(i,j)<=sqr((ull)2*(ull)r)) b[i][j]=b[j][i]=1;
			}
			if(a[i][2]<=r) b[i][n+1]=b[n+1][i]=1;
			if(a[i][2]>=h-r) b[i][n+2]=b[n+2][i]=1;
		}
		bfs();
		if(bz[n+2]) printf("Yes\n");else printf("No\n");
	}
	fclose(stdin);fclose(stdout);
	return 0;
}

d2t2

#include<cstdio>
#include<cstring>
#include<algorithm>
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define N 14
#define M 4100
#define INF 1010580540
using namespace std;
int n,m,a[N][N],e[N],b[M][M],c[M][N],f[M],g[M],bz[M],d[1010000],d1[1010000],ans=INF;
int main()
{
	freopen("treasure.in","r",stdin);
	freopen("treasure.out","w",stdout);
	e[0]=1;fo(i,1,12) e[i]=e[i-1]*2;
	memset(a,60,sizeof(a));
	memset(c,60,sizeof(c));
	memset(g,60,sizeof(g));
	memset(f,60,sizeof(f));
	scanf("%d%d",&n,&m);
	fo(i,1,m)
	{
		int x,y,z;scanf("%d%d%d",&x,&y,&z);
		if(z<a[x][y]) a[x][y]=a[y][x]=z;
	}
	fo(i,1,n)
		fo(s,1,e[n]-1)
		if((s&e[i-1])==0)
			fo(j,1,n)
			if((e[j-1]&s)!=0)
				c[s][i]=min(c[s][i],a[j][i]);
	
	fo(s,1,e[n]-1)
		fo(t,1,e[n]-1)
		if((s&t)==0)
			fo(j,1,n)
				if((e[j-1]&t)!=0)
				{
					if(c[s][j]<INF) b[s][t]+=c[s][j];
					else {b[s][t]=INF;break;}
				}
	
	int he=0,ta=0,x=0;
	fo(i,1,n) d[++ta]=e[i-1]=e[i-1],f[e[i-1]]=0;
	while(he<ta)
	{
		int jt=0;
		x++;
		while(he<ta)
		{
			int s=d[++he];
			fo(t,1,e[n]-1)
			if((s&t)==0&&b[s][t]<INF)
			{
				if(f[s]+b[s][t]*x<g[s+t])
				{
					g[s+t]=f[s]+b[s][t]*x;
					if(g[s+t]<ans&&!bz[s+t]) bz[s+t]=1,d1[++jt]=s+t;
				}
			}
		}
		fo(i,1,ta) f[d[i]]=INF;
		fo(i,1,jt) 
		{
			bz[d1[i]]=0;
			if(d1[i]!=e[n]-1) d[i]=d1[i],f[d1[i]]=g[d1[i]];
			else ans=min(ans,g[d1[i]]);
			g[d1[i]]=INF;
		}
		he=0,ta=jt;
	}
	printf("%d\n",ans);
	fclose(stdin);fclose(stdout);
	return 0;
}

歡迎大佬指正