模擬題1
NOIP2016提高組模擬賽
——By wangyurzee7
中文題目名稱 |
迷妹 |
膜拜 |
換數遊戲 |
英文題目與子目錄名 |
fans |
mod |
game |
可執行文件名 |
fans |
mod |
game |
輸入文件名 |
fans.in |
mod.in |
game.in |
輸出文件名 |
fans.out |
mod.out |
game.out |
每個測試點時限 |
1秒 |
1秒 |
1秒 |
測試點數目 |
20 |
16 |
16 |
每個測試點分值 |
10 |
6.25 |
6.25 |
題目類型 |
傳統 |
傳統 |
傳統 |
運行內存上限 |
128M |
128M |
256M |
註意:評測時不打開任何優化開關
測試數據:
鏈接: http://pan.baidu.com/s/1eRDK43w 密碼: 6sbj
迷妹
(fans.cpp/c/pas)
【問題描述】
小鐘、小皓和小曦都是著名偶像派OI選手,他們都有很多迷妹。
現在,有n個妹子排成了一行,從左到右編號為1到n。這些妹子中,任意一個都是其中一個人的迷妹。
現在,蒟蒻wyz有Q個問題,第i個問題為:編號在l[i]到r[i]範圍內的妹子中,分別有幾個小鐘的迷妹、小皓的迷妹、和小曦的迷妹。
【輸入格式】
輸入到fans.in
第一行2個正整數n,Q。
第2行到第n+1行每行一個正整數a[i],描述了第i個妹子是誰的迷妹。a[i]=1表示小鐘的迷妹,a[i]=2表示小皓的迷妹,a[i]=3表示小曦的迷妹。
第n+2行到第n+Q+1行,每行2個整數,表示第i個問題。
【輸出格式】
輸出到fans.out
共Q行,每行3個用空格分開的整數,分別表示對於第i個問題,有多少小鐘、小皓、小曦的迷妹。
【輸入輸出樣例】
fans.in |
fans.out |
6 3 2 1 1 3 2 1 1 6 3 3 2 4 |
3 2 1 1 0 0 2 0 1 |
【數據範圍】
對於10%的數據,保證1<=n<=10,Q<=10,
對於25%的數據,保證1<=n<=100,Q<=100,
對於45%的數據,保證1<=n<=1000,Q<=1000,
對於100%的數據,保證1<=n<=100,000,Q<=100,000。
保證1<=a[i]<=3,1<=l[i]<=r[i]<=n。
#include<iostream> #include<cstring> #include<cstdio> using namespace std; int n,q,x,le,ri; int a[100010],b[100010],c[100010]; int main() { freopen("fans.in","r",stdin); freopen("fans.out","w",stdout); scanf("%d%d",&n,&q); for(int i=1;i<=n;i++) { scanf("%d",&x); switch(x) { case 1:{a[i]=a[i-1]+1;b[i]=b[i-1];c[i]=c[i-1];break;} case 2:{b[i]=b[i-1]+1;c[i]=c[i-1];a[i]=a[i-1];break;} case 3:{c[i]=c[i-1]+1;a[i]=a[i-1];b[i]=b[i-1];break;} } } for(int i=1;i<=q;i++) { scanf("%d%d",&le,&ri); printf("%d %d %d\n",a[ri]-a[le-1],b[ri]-b[le-1],c[ri]-c[le-1]); } fclose(stdin);fclose(stdout); return 0; }
膜拜
(mod.cpp/c/pas)
【問題描述】
有一個n個點m條邊的有向圖,wyz可以從1號點出發在圖上走,並且最終需要回到1號點。每個點都有一個神犇(包括1號點),每次經過一個沒到過的點,wyz都會膜拜那位神犇。wyz希望膜拜盡可能多的神犇。
由於wyz膜拜神犇的欲望非常強烈,所以他可以有一次機會逆著一條有向邊的方向走。(需要註意的是,這條邊的方向不會改變)
你現在想知道,wyz最多能膜拜多少神犇?
【輸入格式】
輸入到mod.in
第一行2個整數n、m,分別表示圖的點數和邊數。
第2行到底m+1行,每行兩個整數u,v,描述一條u到v的有向邊。
【輸出格式】
輸出到mod.out
一行一個整數表示wyz最多能膜拜多少神犇。
【輸入輸出樣例】
mod.in |
mod.out |
7 10 1 2 3 1 2 5 2 4 3 7 3 5 3 6 6 5 7 2 4 7 |
6 |
【數據範圍】
對於25%的數據,保證n<=100,m<=250,
對於43.75%的數據,保證n<=3,000,m<=7,000。
對於100%的數據,保證n,m<=100,000。
#include<iostream> #include<cstring> #include<cstdio> using namespace std; #define N 100005 #define M 100005 struct edge{int from,adj,next;}e[M],e0[M]; int n,m,stamp=0,top=0,cnt=0,qhead,qtail; int dfn[N],g[N],color[N],size[N],low[M],stk[N]; int g0[N],degree[N],degree0[N],q[N],f[N],f0[N]; void dfs(int u) { dfn[u]=low[u]=++stamp; stk[top++]=u; for(int i=g[u];i;i=e[i].next) { int v=e[i].adj; if(dfn[v]&&!color[v])low[u]=min(low[u],dfn[v]); if(!dfn[v]) { dfs(v); low[u]=min(low[u],low[v]); } } if(low[u]==dfn[u]) { ++cnt; while(stk[top]!=u) { color[stk[--top]]=cnt; size[cnt]++; } } } void bfs(int s) { memset(f,0,sizeof(f)); qhead=qtail=0; for(int i=1;i<=cnt;i++) if(!degree[i])q[++qtail]=i; f[s]=size[s]; while(qhead<qtail) { int u=q[++qhead]; for(int i=g[u];i;i=e[i].next) { int v=e[i].adj; if(f[u])f[v]=max(f[v],f[u]+size[v]); if(!--degree[v])q[++qtail]=v; } } } void bfs0(int s) { memset(f0,0,sizeof(f0)); qhead=qtail=0; for(int i=1;i<=cnt;i++) if(!degree0[i])q[++qtail]=i; f0[s]=size[s]; while(qhead<qtail) { int u=q[++qhead]; for(int i=g0[u];i;i=e0[i].next) { int v=e0[i].adj; if(f0[u])f0[v]=max(f0[v],f0[u]+size[v]); if(!--degree0[v])q[++qtail]=v; } } } int main() { freopen("mod.in","r",stdin); freopen("mod.out","w",stdout); scanf("%d%d",&n,&m); memset(g,0,sizeof(g)); for(int i=1;i<=m;i++) { scanf("%d%d",&e[i].from,&e[i].adj); e[i].next=g[e[i].from]; g[e[i].from]=i; } memset(dfn,0,sizeof(dfn)); memset(color,0,sizeof(color)); memset(size,0,sizeof(size)); for(int i=1;i<=n;i++) if(!dfn[i])dfs(i); int m0=0,s=color[1]; memset(g,0,sizeof(g)); memset(g0,0,sizeof(g0)); memset(degree,0,sizeof(degree)); memset(degree0,0,sizeof(degree0)); for(int i=1;i<=m;i++) if(color[e[i].from]!=color[e[i].adj]) { ++m0; e[m0].from=color[e[i].from]; e[m0].adj=color[e[i].adj]; e[m0].next=g[e[m0].from]; g[e[m0].from]=m0; ++degree[e[m0].adj]; e0[m0].from=e[m0].adj; e0[m0].adj=e[m0].from; e0[m0].next=g0[e0[m0].from]; g0[e0[m0].from]=m0; ++degree0[e0[m0].adj]; } bfs(s);bfs0(s); int ans=size[s]; for(int i=1;i<=m0;i++) if(f[e0[i].from]&&f0[e0[i].adj]) ans=max(ans,f[e0[i].from]+f0[e0[i].adj]-size[s]); printf("%d\n",ans); fclose(stdin);fclose(stdout); return 0; }
換數遊戲
(game.cpp/c/pas)
【問題描述】
鹹魚wyz最近沈迷於一款遊戲,叫做換數遊戲。
遊戲開始時,有n個1到40之間的整數排成一排。wyz每次可以將兩個相鄰的相等的正整數替換成一個比原數大一的正整數(需要註意的是,合並後的數可以大於40)。
wyz可以在任意時刻結束遊戲。結束時wyz的得分為所有剩余的數中最大的數。
現在給定一個初始局面,你想知道wyz能獲得的最高得分。
【輸入格式】
輸入到game.in
第一行一個正整數n。
第2行到第n+1行每行一個正整數,描述第i個數a[i]。
【輸出格式】
輸出到game.out
一行一個整數表示wyz能夠獲得的最高得分。
【輸入輸出樣例】
game.in |
game.out |
4 1 1 1 2 |
3 |
【數據範圍】
對於6.25%的數據,保證n<=5。
對於12.5%的數據,保證n<=20。
對於43.75%的數據,保證n<=1024。
對於100%的數據,保證n<=262144。
數據保證1<=a[i]<=40。
#include<cstdio> #include<cstring> #define N 300005 int ans=0,a[N],n,nxt[N]; int main() { freopen("game.in","r",stdin); freopen("game.out","w",stdout); scanf("%d",&n); for(int i=1;i<=n;i++)scanf("%d",&a[i]); memset(nxt,0,sizeof(nxt)); for(int k=1;k<=60;k++) for(int i=1;i<=n;i++) if(a[i]==k)nxt[i]=i+1,ans=k; else if(nxt[i]&&nxt[nxt[i]])nxt[i]=nxt[nxt[i]],ans=k; else nxt[i]=0; printf("%d\n",ans); fclose(stdin);fclose(stdout); return 0; }
模擬題1