9.2NOIP模擬題
9.2 NOIP模擬
題目名稱 |
“與” |
小象塗色 |
行動!行動! |
輸入文件 |
and.in |
elephant.in |
move.in |
輸出文件 |
and.out |
elephant.in |
move.in |
時間限制 |
1s |
1s |
1s |
空間限制 |
64MB |
128MB |
128MB |
“與”
(and.pas/.c/.cpp)
時間限制:1s;空間限制64MB
題目描述:
給你一個長度為n的序列A,請你求出一對Ai,Aj(1<=i<j<=n)使Ai“與”Aj最大。
Ps:“與”表示位運算and,在c++中表示為&。
輸入描述:
第一行為n。接下來n行,一行一個數字表示Ai。
輸出描述:
輸出最大的Ai“與”Aj的結果。
樣例輸入:
3
8
10
2
樣例輸出:
8
樣例解釋:
8 and 10 = 8
8 and 2 = 0
10 and 2 = 2
數據範圍:
20%的數據保證n<=5000
100%的數據保證 n<=3*10^5,0<=Ai<=10^9
/* "與"是要求同一位均是1,結果才為1。而對於2進制,越高位有1,數字越大。 所以我們可以考慮將所給數列的數字看成二進制,從二進制最高位向下枚舉 若有大於等於兩個數"這一位上為1",那麽最終結果的這一位肯定是1, 於是我們就可以將所有"這一位上為1"的數保留下來, 剩下的數舍棄;而若有少於兩個數"這一位上為1",則這一位上一定為0。 */ #include<cstdio> #include<cstring> #include<cstdlib> #include<iostream> #include<cmath> #include<algorithm> using namespace std; int n,a[300002],d[35],ans; void init() { scanf("%d",&n); for(int i=1; i<=n; i++) scanf("%d",&a[i]); } void find() { int i,j,ct,now=n,t; for(i=30; i>=0; i--) { ct=0; for(j=1; j<=now; j++) if(a[j]&(1<<i)) ct++; if(ct<2) continue; t=0;d[i]=1; for(j=1; j<=now; j++) if(a[j]&(1<<i)) a[++t]=a[j]; now=t; } for(i=30; i>=0; i--) if(d[i]) ans=ans^(1<<i); printf("%d\n",ans); } int main() { freopen("and.in","r",stdin); freopen("and.out","w",stdout); init();find(); return 0; }
小象塗色
(elephant.pas/.c/.cpp)
時間限制:1s,空間限制128MB
題目描述:
小象喜歡為箱子塗色。小象現在有c種顏色,編號為0~c-1;還有n個箱子,編號為1~n,最開始每個箱子的顏色為1。小象塗色時喜歡遵循靈感:它將箱子按編號排成一排,每次塗色時,它隨機選擇[L,R]這個區間裏的一些箱子(不選看做選0個),為之塗上隨機一種顏色。若一個顏色為a的箱子被塗上b色,那麽這個箱子的顏色會變成(a*b)mod c。請問在k次塗色後,所有箱子顏色的編號和期望為多少?
輸入描述:
第一行為T,表示有T組測試數據。
對於每組數據,第一行為三個整數n,c,k。
接下來k行,每行兩個整數Li,Ri,表示第i個操作的L和R。
輸出描述:
對於每組測試數據,輸出所有箱子顏色編號和的期望值,結果保留9位小數。
樣例輸入:
3
3 2 2
2 2
1 3
1 3 1
1 1
5 2 2
3 4
2 4
樣例輸出:
2.062500000
1.000000000
3.875000000
數據範圍:
40%的數據1 <= T <= 5,1 <= n, k <= 15,2 <= c <= 20
100%的數據滿足1 <= T <= 10,1 <= n, k <= 50,2 <= c <= 100,1 <= Li <= Ri <= n
/* dp[i][j][k]表示第i個箱子第j次染色,染為k顏色的概率。 時間復雜度過高,只能拿部分分 對於每個箱子,它們的本質是相同的,也就是第幾個箱子這一維狀態是不需要存在的。 dp[i][j]表示染色i次顏色為j的概率 dp[i+1][j]+=dp[i][j]/2; 上次不染色 dp[i+1][j*x%c]+=dp[i][j] /2 /c; (x枚舉顏色) 上次染色,染成x 最後期望Σdp[cnt[i]][j]*j; */ #include<iostream> #include<cstdio> #include<cstring> #define N 107 using namespace std; int n,m,tot,c,k,t,l,r,cnt[N]; double dp[N][N],ans; void init() { memset(dp,0,sizeof dp); memset(cnt,0,sizeof cnt); tot=0;ans=0; scanf("%d%d%d",&n,&c,&k); for(int i=1;i<=k;i++) { scanf("%d%d",&l,&r); for(int j=l;j<=r;j++) { cnt[j]++;tot=max(tot,cnt[j]); } } } void DP() { dp[0][1]=1; for(int i=0;i<tot;i++) { for(int j=0;j<c;j++) { dp[i+1][j]+=dp[i][j]/2; for(int x=0;x<c;x++) dp[i+1][(j*x)%c]+=dp[i][j]/(2*c); } } for(int i=1;i<=n;i++) for(int j=0;j<c;j++) ans+=dp[cnt[i]][j]*j; printf("%.9f\n",ans); } int main() { scanf("%d",&t); while(t--) { init();DP(); } return 0; }
行動!行動!
(move.pas/.c/.cpp)
時間限制:1s;空間限制:128MB
題目描述:
大CX國的大兵Jack接到一項任務:敵方占領了n座城市(編號0~n-1),有些城市之間有雙向道路相連。Jack需要空降在一個城市S,並徒步沿那些道路移動到T城市。雖然Jack每從一個城市到另一個城市都會受傷流血,但大CX國畢竟有著“過硬”的軍事實力,它不僅已經算出Jack在每條道路上會損失的血量,還給Jack提供了k個“簡易急救包”,一個包可以讓Jack在一條路上的流血量為0。Jack想知道自己最少會流多少血,不過他畢竟是無腦的大兵,需要你的幫助。
輸入描述:
第一行有三個整數n,m,k,分別表示城市數,道路數和急救包個數。
第二行有兩個整數,S,T。分別表示Jack空降到的城市編號和最終要到的城市。
接下來有m行,每行三個整數a,b,c,表示城市a與城市b之間有一條雙向道路。
輸出描述:
Jack最少要流的血量。
樣例輸入:
5 6 1
0 3
3 4 5
0 1 5
0 2 100
1 2 5
2 4 5
2 4 3
樣例輸出:
8
數據範圍:
對於30%的數據,2<=n<=50,1<=m<=300,k=0;
對於50%的數據,2<=n<=600,1<=m<=6000,0<=k<=1;
對於100%的數據,2<=n<=10000,1<=m<=50000,0<=k<=10.
/* 分層圖spfa 應該只有70,卡spfa...要加優化,懶得加了。 */ #include<iostream> #include<cstdio> #include<cstring> #define N 10001 #define M 100001 using namespace std; int head[N],d[N][11],q[M][2]; bool inq[N][11]; int n,m,k,st,ed,cnt; struct edge { int u,to,dis,next; }e[M]; inline int read() { int x=0,f=1;char c=getchar(); while(c>‘9‘||c<‘0‘){if(c==‘-‘)f=-1;c=getchar();} while(c>=‘0‘&&c<=‘9‘){x=x*10+c-‘0‘;c=getchar();} return x*f; } inline void add(int u,int to,int dis) { e[++cnt].to=to;e[cnt].dis=dis;e[cnt].next=head[u];head[u]=cnt; } void spfa() { memset(d,127/3,sizeof d); int he=0,ta=1; q[0][0]=st;q[0][1]=0; inq[st][0]=1;d[st][0]=0; while(he!=ta) { int now=q[he][0],tmp=q[he++][1];inq[now][tmp]=0; if(he==100001) he=0; for(int i=head[now];i;i=e[i].next) { int v=e[i].to; if(d[v][tmp]>d[now][tmp]+e[i].dis) { d[v][tmp]=d[now][tmp]+e[i].dis; if(!inq[v][tmp]) { q[ta][0]=v;q[ta++][1]=tmp; inq[v][tmp]=1; if(ta==100001) ta=0; } } if(d[v][tmp+1]>d[now][tmp] && tmp<k) { d[v][tmp+1]=d[now][tmp]; if(!inq[v][tmp+1]) { inq[v][tmp+1]=1; q[ta][0]=v;q[ta++][1]=tmp+1; if(ta==100001) ta=0; } } } } int ans=0x7fffffff; for(int i=0;i<=k;i++) ans=min(ans,d[ed][i]); printf("%d",ans); } int main() { int x,y,z; n=read();m=read();k=read(); st=read();ed=read(); while(m--) { x=read();y=read();z=read(); add(x,y,z);add(y,x,z); } spfa(); return 0; }
9.2NOIP模擬題