【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;
}