生活随笔
收集整理的這篇文章主要介紹了
牛客练习赛 69
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
第一次打牛客直接。。。
y1s1牛客的評測系統真的慢,搞得我不想交
B - 劃分
題目鏈接
首先先對數組a[]逆序貪心可得val(i,j)=a1+a2+?+ai×jval(i,j)=a_1+a_2+\dots+a_{i×j}val(i,j)=a1?+a2?+?+ai×j?
嘗試證明:分析可知我們最終會選擇i×ji×ji×j個數組a[]的數,貪心肯定每個數選的越大越好,嘗試每一組的前jjj大的數都是數組中前i×ji×ji×j大的數的子集,即可將原數組分成iii個部分選出前i×ji×ji×j大。
#include<iostream>
#include<algorithm>
using namespace std
;
const int N
=100010;
typedef long long ll
;
ll a
[N
],s
[N
];
int n
;
int x
,y
;
int main()
{cin
>>n
;for(int i
=1;i
<=n
;i
++) cin
>>a
[i
];cin
>>x
>>y
;sort(a
+1,a
+1+n
);reverse(a
+1,a
+1+n
);for(int i
=1;i
<=n
;i
++) s
[i
]=s
[i
-1]+a
[i
];ll res
=0;for(int i
=1;i
<=x
;i
++)for(int j
=1;j
<=y
;j
++)res
+=s
[i
*j
];cout
<<res
<<endl
;return 0;
}
C - 旅行
題目鏈接
對于一個連通圖,嘗試去掉一些邊,但是最終保證圖連通而且留下的邊盡量的大,如果我們用kurskal求最大生成樹剛好滿足上述需求。我們在求dist(u,v)dist(u,v)dist(u,v)時,只走最大生成樹上的邊一定能保證dist(u,v)dist(u,v)dist(u,v)最大。選擇排列時,對于每條邊最少都要經過一次,答案一定不會超過最大生成樹上的邊權和。嘗試構造一種解使得答案等于最大生成樹上的邊權和:依次選擇最小的邊的兩個點,然后把這條邊刪去(意思為不能再次選擇該邊),這樣構造即可構造出最優答案。
#include<iostream>
#include<algorithm>
using namespace std
;
typedef long long ll
;
const int N
=500010;
struct node
{int a
,b
,w
;bool operator <(const node
& o
)const{return w
>o
.w
;}
}e
[N
];
int n
,m
;
int p
[N
];
int find(int x
)
{return x
==p
[x
]?x
:p
[x
]=find(p
[x
]);
}
int main()
{cin
>>n
>>m
;for(int i
=0;i
<m
;i
++) cin
>>e
[i
].a
>>e
[i
].b
>>e
[i
].w
;for(int i
=1;i
<=n
;i
++) p
[i
]=i
;sort(e
,e
+m
);ll res
=0;for(int i
=0;i
<m
;i
++){int a
=e
[i
].a
,b
=e
[i
].b
,w
=e
[i
].w
;int pa
=find(a
),pb
=find(b
);if(pa
!=pb
){p
[pa
]=pb
;res
+=w
;}}cout
<<res
<<endl
;return 0;
}
補完2題,發現牛客的思維難度還是挺高的,如果能夠推出結論,還是挺好寫代碼的,以后要多練練這種思維+算法題目。
D - 火柴排隊
剛開始看還以為是個數論題數論渣渣不想看數論,其實是個dp
狀態表示:f[i][j][0/1]f[i][j][0/1]f[i][j][0/1]表示對于前iii個人選擇jjj個增加ddd 并且不選/選擇第iii個人
狀態計算:
f[i][j][0]=f[i?1][j][0]+(a[i?1]+d≤a[i])f[i?1][j][1]f[i][j][0]=f[i-1][j][0]+(a[i-1]+d \leq a[i])f[i-1][j][1]f[i][j][0]=f[i?1][j][0]+(a[i?1]+d≤a[i])f[i?1][j][1]
f[i][j][1]=f[i?1][j?1][0]+f[i?1][j?1][1]f[i][j][1]=f[i-1][j-1][0]+f[i-1][j-1][1]f[i][j][1]=f[i?1][j?1][0]+f[i?1][j?1][1]
很多dp概率實質都是算方案數,然后借用階乘和逆元算答案。
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std
;
typedef long long ll
;
const int N
=5010;
const ll mod
=998244353;
ll a
[N
],d
;
ll f
[2][N
][2];
int n
;
ll fact
[N
],infact
[N
];
ll
qmi(ll a
,ll b
,ll p
)
{ll res
=1;while(b
){if(b
&1) res
=res
*a
%p
;a
=a
*a
%mod
;b
>>=1;}return res
;
}
void init(int n
)
{fact
[0]=infact
[0]=1;for(int i
=1;i
<=n
;i
++){fact
[i
]=fact
[i
-1]*i
%mod
;infact
[i
]=qmi(fact
[i
],mod
-2,mod
);}
}int main()
{cin
>>n
>>d
;init(n
);for(int i
=1;i
<=n
;i
++) cin
>>a
[i
];sort(a
+1,a
+1+n
);f
[0][0][0]=1;for(int i
=1;i
<=n
;i
++){for(int j
=0;j
<=i
;j
++){if(j
) f
[i
&1][j
][1]=(f
[i
-1&1][j
-1][0]+f
[i
-1&1][j
-1][1])%mod
;f
[i
&1][j
][0]=(f
[i
-1&1][j
][0]+f
[i
-1&1][j
][1]*(a
[i
-1]+d
<=a
[i
]))%mod
;}}for(int i
=1;i
<=n
;i
++){ll res
=((f
[n
&1][i
][0]+f
[n
&1][i
][1])%mod
*fact
[n
-i
]%mod
*fact
[i
]%mod
*infact
[n
]%mod
+mod
)%mod
;cout
<<res
<<endl
;}
}
要加油哦~
創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎
總結
以上是生活随笔為你收集整理的牛客练习赛 69的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。