1. 程式人生 > >【NOIP模擬】K進位制+排隊+航班

【NOIP模擬】K進位制+排隊+航班

                                                     K進位制

描述

給定一個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 <bits/stdc++.h>
using namespace std;

const int Max=100005;
int t,n,m,num[Max],sum;
char ch[Max];

inline int ksm(int a,int b,int mod)
{
	int ans=1;
	a%=mod;
	while(b)
	{
	  if(b&1) ans=(ans*a)%mod;
	  b>>=1;
	  a=(a*a)%mod;
	}
	return ans;
}

inline bool check()
{
	sum=0;
	for(int i=1;i<=n;i++)
	  if(ch[i]>='A') num[i]=(ch[i]-'A')+10;
	  else num[i]=ch[i]-'0';
	for(int i=1;i<=n;i++)
	  sum=(sum+num[i]*ksm(m,n-i,m-1))%(m-1);
	return !sum;
}

int main()
{
	scanf("%d\n",&t);
	while(t--)
	{
	  scanf("%d%s",&m,ch+1);
	  n=strlen(ch+1);
	  if(check()) printf("yes\n"); 
	  else printf("no\n");
	}
	return 0;
}

                                                         排隊

描述

在成都某中學有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 ).

解析:        可以將原問題轉化一下,看成是在一個二維平面上行走,女生看向右移動,男生看成向上移動,那麼到達(N,M)點且路線又不走到y=x這條直線上方的路線總數就是答案,這個組合問題很經典,方案數為C(M+N,M)-(M+N,M-1),所以可以知道答案就是1-M/(N+1) 。(注意本來因為男生和女生中兩兩不同要乘n!m!但是可以約掉)。

程式碼:

#include <bits/stdc++.h>
using namespace std;

int t;
double n,m;

int main()
{
	scanf("%d",&t);
	while(t--)
	{
	  scanf("%lf%lf",&n,&m);
	  if(n<m) printf("%.6f\n",0);
	  else printf("%.6f\n",1-(m/(n+1)));
	}
	return 0;
}

                                                        航班

描述

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。

程式碼:

#include <bits/stdc++.h>
using namespace std;

const int Max=200100;
int n,m,Index,cnt,tot,size=1;
int num[Max],low[Max],father[Max],p[Max],vis[Max];
int first[Max],f[Max][3],First[Max],ans[Max],son[Max];
struct shu{int to,next,len;};
shu edge[Max<<1],Edge[Max<<1];

inline int get_int()
{
	int x=0,f=1;
	char c;
	for(c=getchar();(!isdigit(c))&&(c!='-');c=getchar());
	if(c=='-') f=-1,c=getchar();
	for(;isdigit(c);c=getchar()) x=(x<<3)+(x<<1)+c-'0';
	return x*f;
}
inline void print(int x)
{
	if(x<0) x=-x,putchar('-');
	if(x>9) print(x/10);
	putchar('0'+x%10);
}

inline void build(int x,int y,int z)
{
	edge[++size].next=first[x];
	first[x]=size;
	edge[size].to=y,edge[size].len=z;
}

inline void Build(int x,int y,int z)
{
	Edge[++size].next=First[x];
	First[x]=size;
	Edge[size].to=y,Edge[size].len=z;
}

inline void tarjan(int point,int v)
{
	num[point]=low[point]=++Index;
	p[++tot]=point;
	for(int u=first[point];u;u=edge[u].next)
	{
	  int to=edge[u].to;
	  if((u^1)==v) continue;
	  if(!num[to]) tarjan(to,u),low[point]=min(low[point],low[to]);
	  else low[point]=min(low[point],num[to]);
	}
	if(low[point]==num[point])
	{
	  cnt++;
	  while(1)
	  {
	  	int x=p[tot--];
	  	father[x]=cnt;
	  	if(x==point) break;
	  }
	}
}

inline void rebuild()
{
	size=0;
	for(int i=1;i<=n;i++)
	  for(int u=first[i];u;u=edge[u].next)
	    if(father[i]!=father[edge[u].to]) Build(father[i],father[edge[u].to],edge[u].len);
}

inline void dfs1(int point)
{
	vis[point]=1;
	for(int u=First[point];u;u=Edge[u].next)
	{
	  int to=Edge[u].to;
	  if(vis[to]) continue;
	  dfs1(to);
	  if(f[to][0]+Edge[u].len>f[point][0])
	    son[point]=to,f[point][1]=f[point][0],f[point][0]=f[to][0]+Edge[u].len;
	  else f[point][1]=max(f[point][1],f[to][0]+Edge[u].len);
	}
}

inline void dfs2(int point)
{
	vis[point]=1;
	for(int u=First[point];u;u=Edge[u].next)
	{
	  int to=Edge[u].to;
	  if(vis[to]) continue;
	  if(to==son[point]) f[to][2]=max(f[point][2],f[point][1])+Edge[u].len;
	  else f[to][2]=max(f[point][2],f[point][0])+Edge[u].len;
	  dfs2(to);
	}
}

inline int mx(int x,int y){return x<y?y:x;}

int main()
{
	n=get_int(),m=get_int();
	for(int i=1;i<=m;i++)
	{
	   int x=get_int(),y=get_int(),z=get_int();
	   build(x,y,z),build(y,x,z);
	}
	for(int i=1;i<=n;i++) if(!num[i]) tarjan(i,0);
	rebuild();
	dfs1(1);
	memset(vis,0,sizeof(vis));
	dfs2(1);
	for(int i=1;i<=cnt;i++) ans[i]=mx(f[i][0],f[i][2]);
	for(int i=1;i<=n;i++) print(ans[father[i]]),putchar('\n');
	return 0;
}