1. 程式人生 > >2018提高組模擬9(未完)

2018提高組模擬9(未完)

2018提高組模擬9

—————————————————————————————————————————20181004

T1

K進位制

(WOJ4036)

【模擬||數論】

描述

給定一個K(2<=K<=16)進位制數a,判斷a是否能被K-1整除。

輸入

第一行是一個整數t(1<=t<=50),表示測試點數量。

對於每組資料,第一行一個整數K,表示進位制。

第二行一個K進位制數,表示a。保證a是合法的K進位制數,沒有前導0,且只由’0’-‘9’、’A’-‘F’構成。

輸出

如果a可以被K-1整除,輸出”yes”,否則輸出”no”。

樣例輸入

2 16 2D 10 19

樣例輸出

yes no

提示

對於40%的資料,a的長度不超過5。

對於100%的資料,a的長度不超過100000。

題解

像十進位制的除法的豎式一樣模擬就好了

當然還有一種神奇做法:

#include<iostream>
#include<cstring>
#include<cmath>
#include<cstdio>
using namespace std;
int t,k;
char c[100010];
void solve(){
	int len=strlen(c+1),now=0;
	for(int i=1;i<=len;++i){
		now*=k;
		if(isdigit(c[i]))now+=(c[i]^48);
		else now+=(c[i]-'A'+10);
		now%=(k-1);
	}
	if(!now)printf("yes\n");
	else printf("no\n");
}
int main(){
	scanf("%d",&t);
	while(t--){
		scanf("%d",&k);
		scanf("%s",c+1);
		solve();
	}
	return 0;
}

T2

(WOJ4037)

 排隊

描述

在成都某中學有m個男生與n個女生排隊,這個學校的女生比較古怪,從某個位置(包含這個位置)開始往前數,男生的數量超過了女生的數量,女生會感覺不安全,於是會大叫起來,為了構建和諧校園,安排隊伍時應該避免這樣的情況。請你計算出不會引發尖叫的排隊方案的概率。(排隊方案不同定義:當且僅當某個某個位置人不一樣,如男生A、男生B ,與男生B、男生A ,2個排列是不同方案)

輸入

第一行1個整數, 表示測試資料的組數。

每個資料 有兩個數 N,M(N個女生,M個男生)

輸出

對於每組資料,輸出一個實數(保留到小數點後 6 位)

樣例輸入

3 1 0 0 1 1 1

樣例輸出

1.000000 0.000000 0.500000

提示

【 Hint】

第一組:只有一個女生,一種方案且可行

第二組:只有1個男生,一種方案且不行

第三組:兩種方案 女、男可行,男、女不可行,可行概率0.5

【資料規模】

30%的資料: (測試組數<=10),(0<=N,M<=1000).

100%的資料: (測試組數=9008 ), ( 0<=N,M<=20000 ).

題解

數學找規律

先打一個暴利程式,然後小資料輸入看結果,很有規律的!!

暴力程式:

#include<cstdio>
#include<iostream>
using namespace std;
inline int read(){
	int x=0;char c=getchar();
	while(!isdigit(c))c=getchar();
	while(isdigit(c)){x=(x<<3)+(x<<1)+(c^48);c=getchar();}
	return x;
}
int t,a,b;
int dfs(int now,int g,int bo){
	if(bo>g)return 0;
	if(now>a+b)return 1;
	int ans=0;
	if(g<a)ans+=dfs(now+1,g+1,bo);
	if(bo<b)ans+=dfs(now+1,g,bo+1);
	return ans;
}
int bb(int x){
	if(x==1)return 1;
	if(x<1)return 1;
	return x*bb(x-1);
}
int main(){
	t=read();
	while(t--){
		a=read();b=read();// 女   男 
		if(b>a){
			printf("0.000000\n");
			continue;
		}
		printf("%lf\n",1ll*dfs(1,0,0)*bb(a)*bb(b)*1.000000/bb(a+b));
	}
	return 0;
}

正解(轉換方式很多)

  可以將原問題轉化一下,看成是在一個二維平面上行走,女生看成移動(1,0),男生看成移動(0,1),

那麼到達(N,M)點且路線又不走到y=x 這條直線上方的路線總數就是答案,

這個組合問題很經典,方案數為 C(M+N,M)-(M+N,M-1),所以可以知道答案就是1-M/(N+1) 

#include<cstdio>
#include<iostream>
using namespace std;
inline int read(){
	int x=0;char c=getchar();
	while(!isdigit(c))c=getchar();
	while(isdigit(c)){x=(x<<3)+(x<<1)+(c^48);c=getchar();}
	return x;
}
int t,a,b;
int main(){
	t=read();
	while(t--){
		a=read();b=read();// 女   男 
		if(b>a||(b==0&&a==0)){
			printf("0.000000\n");
			continue;
		}
		printf("%.6lf\n",(double)(a-b+1)/(double)(a+1));
	}
	return 0;
}

T3

(WOJ4038)

(tarjan無向圖邊雙連通分量+樹形DP)

航班

描述

L因為業務繁忙,經常會到處出差。因為他是航空公司的優質客戶,於是某個航空公司給了他一個優惠券。

他可以利用這個優惠券在任何一個國家內的任意城市間免費旅行,當他的路線跨國才會產生費用。L有一個航空公司的價格表與航線。而且每個城市出發都能到所有的城市,2個城市間可能有不止一個航班,一個國家內的2個城市間一定有不同的路線,但是不同國家的城市間只有一條路線。L想知道從每個城市出發到產生費用最多的城市,不過你不能重複在一個航班上飛來飛去產生費用,必須沿最少的費用路線飛行

輸入

第一行,兩個整數 N,M,表示N 個城市, M 條航線。

接下來 M 行,每行三個整數 a,b,c,表示城市 a,b 之間有一條費用為 c 的航線。

輸出

共 N 行,第 i 行為從城市 i 出發到達每個城市額外費用的最大值。

樣例輸入

6 6 1 4 2 1 2 6 2 5 3 2 3 7 6 3 4 3 1 8

樣例輸出

4 4 4 6 7 7

提示

【解釋】

有四個國家,包含的城市分別為 {1,2,3},{4},{5},{6}。

從城市 1 出發到達城市 6,乘坐(1,3)(3,6)兩個航班費用最大,(1,3)在國內為免費航班, (3,6)的費用為 4,所以從 1 出發的最大費用為 4。

【資料規模】

對於 40%的資料 1<=N<=1000,1<=M<=1000

對於 100%的資料 1<=N<=20000,1<=M<=200000

題解

先用無向圖邊雙連通分量縮點,再用一個樹形DP就好了

方案一:

兩次dfs/樹形dp求直徑的2個端點A,B,

則 x到最遠距離的距離是 MAX(dis(x,A),dis(x,B)) 

方案二:

樹形DP換根法

記錄每一個點向下的最大值與次大值

對於每一個點,需求的最大答案就是:

從父親走到自己的兄弟,或從父親走到自己的祖父,或由自己走到自己的兒孫

………………………………