0 淘汰賽制
淘汰賽制是一種極其殘酷的比賽制度。2n名選手分別標號1,2,3,……2n-1,2^n,他們將要參加n輪的激烈角逐。每一輪中,將所有參加該輪的選手按標號從小到大排序後,第1位與第2位比賽,第3位與第4位比賽,第5位與第6位比賽……只有每場比賽的勝者纔有機會參加下一輪的比賽(不會有平局)。這樣,每輪將淘汰一半的選手。n輪過後,只剩下一名選手,該選手即爲最終的冠軍。
現在已知每位選手分別與其他選手比賽獲勝的概率,請你預測一下誰奪冠的概率最大。
30%的數據滿足n<=3
100%的數據滿足n<=10
DP快樂
用f[i][j]表示第i輪比賽,j位選手獲勝的概率
轉移有
觀察一個選手在某一輪中可能對戰的選手,確定k的值
#include <cstdio>
using namespace std;
int n,m,s,d=1;
double f[15][1050],a[1050][1050],ans;
int cd(int x){
return (x-1)/d+1;
}
int main(){
scanf("%d",&n);
m=1;
for (int i=1;i<=n;i++) m*=2;
for (int i=1;i<=m;i++){
f[0][i]=1;
for (int j=1;j<=m;j++){
int d;
scanf("%d",&d);
a[i][j]=d;
double c=100;
a[i][j]=a[i][j]/c;
}
}
for (int i=1;i<=n;i++){
for (int j=1;j<=m;j++){
f[i][j]=f[i-1][j];
double l=0;
int t=cd(j);
if (t&1) t+=1;else t-=1;
for (int k=1;k<=m;k++)
if (cd(k)==t)
l+=f[i-1][k]*a[j][k];
f[i][j]*=l;
}
d*=2;
}
for (int i=1;i<=m;i++)
if (f[n][i]>ans){
ans=f[n][i];s=i;
}
printf("%d",s);
}
1 方程的解
佳佳碰到了一個難題,請你來幫忙解決。 對於不定方程a1+a2+……+ak-1+ak=g(x),其中k>=2且k∈N*,x是正整數,g(x)=x^x mod 1000(即xx除以1000的餘數),x,k是給定的數。我們要求的是這個不定方程的正整數解組數。 舉例來說,當k=3,x=2時,分別爲(a1,a2,a3)=(2,1,1),(1,2,1),(1,1,2).
對於40%的數據,ans<=10^16; 對於100%的數據,k<=100,x<=2^31-1,k<=g(x)。
g(x)好求,隨便快速冪
但是我當時就是沒想到怎麼求方案[我明白了我就是很菜我這就去辦退學手續.jpg]
可發現這個方案數相當於求C(g(x)-1,k-1),隨便用組合數學想想(隔板法?反正我想這個想明白)
然後組合數呢可以約分化簡,分解質因數,加加減減次方,再把次方高精度乘起來
#include <cstdio>
using namespace std;
const int N=1000;
int k,x,l[1000];
int a[1000],p[1000],bz[1000];
void ksm(){
int y=x%1000,b=x;
x=1;
while (b){
if (b&1) x=(x*y)%1000;
y=(y*y)%1000;
b>>=1;
}
}
void pi(){
for (int i=2;i<=1000;i++){
if (bz[i]==0){
p[++p[0]]=i;
}
for (int j=1;j<=p[0]&&p[j]*i<=1000;j++){
bz[p[j]*i]=1;
if (i%p[j]==0) break;
}
}
}
void pri(int x,int b){
for (int i=1;i<=p[0];i++)
if (x<=1)break;else{
int k=0;
while (x%p[i]==0&&x>0){
x/=p[i];
k++;
}
l[i]+=k*b;
}
}
void cd(int x){
int g=0;
for (int i=1;i<=a[0];i++){
a[i]=a[i]*x+g;
g=a[i]/N;
a[i]%=N;
if (i==a[0]&&g>0) ++a[0];
}
}
void plus(){
a[1]=1,a[0]=1;
int k=1;
for (int i=1;i<=p[0];i++)
if (l[i]){
while (l[i]){
k*=p[i];
if (k>=N) cd(k),k=1;
--l[i];
}
}
cd(k);
}
void print(){
printf("%d",a[a[0]]);
for (int i=a[0]-1;i>=1;i--)
printf("%03d",a[i]);
}
int main(){
scanf("%d%d",&k,&x);
ksm();
pi();
for (int i=2;i<=k-1;i++) pri(i,-1);
for (int i=x-k+1;i<=x-1;i++) pri(i,1);
plus();
print();
}
2 物流運輸
物流公司要把一批貨物從碼頭A運到碼頭B。由於貨物量比較大,需要n天才能運完。貨物運輸過程中一般要轉停好幾個碼頭。物流公司通常會設計一條固定的運輸路線,以便對整個運輸過程實施嚴格的管理和跟蹤。由於各種因素的存在,有的時候某個碼頭會無法裝卸貨物。這時候就必須修改運輸路線,讓貨物能夠按時到達目的地。但是修改路線是一件十分麻煩的事情,會帶來額外的成本。因此物流公司希望能夠訂一個n天的運輸計劃,使得總成本儘可能地小。
n( 1 <= n <= 100 )、m( 1 <= m<= 20 )
就是個DP呢
設表示第i天的最小成本
其中a[1][m]是去掉i到j天不能走的碼頭後的最短路
最短路當然可以每次求啦,20的小數據用什麼最短路都可以呢
#include <cstdio>
#include <cstring>
using namespace std;
int n,m,k;
int a[25][25],g[25][25],p[25][105];
int f[105],b[25];
void read(){
int e,d;
scanf("%d%d%d%d",&n,&m,&k,&e);
memset(a,0x3f,sizeof a);
for (int i=1;i<=e;i++){
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
a[x][y]=a[y][x]=(z<a[x][y]?z:a[x][y]);
}
scanf("%d",&d);
for (int i=1;i<=d;i++){
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
for (int j=y;j<=z;j++)
p[x][j]=1;
}
}
void floyed(){
for (int k=1;k<=m;k++){
if (b[k]==0)
for (int i=1;i<=m;i++)
if (i!=k&&b[i]==0)
for (int j=1;j<=m;j++)
if (b[j]==0&&k!=j&&i!=j&&a[i][k]!=a[0][0]
&&a[k][j]!=a[0][0]&&a[i][k]+a[k][j]<a[i][j])
a[i][j]=a[i][k]+a[k][j];
if (b[k]==1)
for (int i=1;i<=m;i++)
a[i][k]=a[k][i]=a[0][0];
}
}
void dp(){
memset(f,0x3f,sizeof f);
f[0]=-k;
for (int i=1;i<=n;i++){
memset(b,0,sizeof b);
memcpy(g,a,sizeof a);
for (int j=i;j>=1;j--){
for (int l=1;l<=m;l++)
if (p[l][j]==1) b[l]=1;
memcpy(a,g,sizeof a);
floyed();
if (a[1][m]==a[0][0]) break;
f[i]=(f[i]>f[j-1]+k+(i-j+1)*a[1][m]?f[j-1]+k+(i-j+1)*a[1][m]:f[i]);
}
memcpy(a,g,sizeof a);
}
}
int main(){
read();
dp();
printf("%d",f[n]);
}
3 矩陣乘法(mat)
給你一個 N*N 的矩陣,不用算矩陣乘法,但是每次詢問一個子矩形的第 K 小數。
矩陣中數字是 10 ^ 9 以內的非負整數;
20% 的數據: N<=100,Q<=1000 ;
40% 的數據: N<=300,Q<=10000 ;
60% 的數據: N<=400,Q<=30000 ;
100% 的數據: N<=500,Q<=60000 。
整體二分,二維樹狀數組
我和我的400寶貝兒
聽說復旦交大清北什麼的裸分的話三總必須400+呢。。。
看着我可憐的分數流下了悔恨的淚水。。。
假如我好好努力是不是可以和我家400寶貝兒重逢呢
從這學期開始再也別欠數學作業,從新學期開始像我同桌一樣好好寫英語筆記,從現在開始好好看語文老師佈置的書
我愛我吒我丙我李靖夫婦我申公公我太乙真人我龍王^ _ ^國漫衝鴨