2025百度之星程序设计大赛初赛第一场
Matiji
每个都可以选或不选(丢给小号),直接dp
#include<bits/stdc++.h>
using namespace std;
const int N=200010;
int f[N][2];
int n,s;
int p[N];
int main( )
{
std::ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
int T;cin>>T;
while(T--){
cin>>n>>s;
for(int i=1;i<=n;i++){
cin>>p[i];
}
//sort(p+1,p+n+1);
f[0][0]=s;f[0][1]=s;
for(int i=1;i<=n;i++){
f[i][1]=max((f[i-1][0]+p[i]+1)/2,(f[i-1][1]+p[i]+1)/2);
f[i][0]=max(f[i-1][0],f[i-1][1]);
}
cout<<max(f[n][0],f[n][1])<<'\n';
}
return 0;
}
Left and Right
能表示的数是[l,r],[2l,2r],[kl,kr],发现之后会重合就都能表示了,所以就把前几个区间中间空着的加起来
l-1 [l,r] 2l-r-1 [2l,2r] 3l-2r-1 [3l,3r]...
令(k+1)l-kr-1>=1,k<=(l-2)/(r-l) 答案就是sum((k+1)l-kr-1)
#include<bits/stdc++.h>
#define int long long
using namespace std;
int l,r;
signed main( )
{
std::ios::sync_with_stdio(false);
int T;cin>>T;
while(T--){
cin>>l>>r;
if(l==1){
cout<<0<<'\n';
}else if(l==r){
cout<<"infty\n";
}else {
int k=(l-2)/(r-l);
//cout<<"get"<<k<<endl;
int t;if(k==0)t=0;else t=(k+3)*k/2*l-(k+1)*k/2*r-k;
// cout<<l-1<<" "<<(k+3)*k/2*l-(k+1)*k/2*r-1<<'\n';
cout<<l-1+t<<'\n';
}
}
return 0;
}
Bus Station
容易发现总能使f(s)=1
考察其中任意一个点,这个点的出边,都要有路径覆盖。出边只有两种情况,一个是和另一个出边合起来作为一条路径跨过这个点,一个是直接以这个点为端点
想要这个点最多只有一个路径将他作为端点,必须将出边两两配对成为条路径,可能剩下一个实在没办法以他为端点。
2k(奇数2k+1)个物品配对,是(2k-1)!!(奇数(2k+1)!!)种方案数
将所有点的答案累乘起来
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int mod=998244353;
const int N=200010;
int n;
int ind[N];
int main( )
{
std::ios::sync_with_stdio(false);
int T;cin>>T;
while(T--){
cin>>n;for(int i=1;i<=n;i++)ind[i]=0;
for(int i=1;i<=n-1;i++){
int u,v;cin>>u>>v;ind[u]++;ind[v]++;
}
int ans=1;
for(int i=1;i<=n;i++){
for(int j=1;j<=ind[i];j+=2){
ans=(1ll*ans*j)%mod;
}
}
cout<<ans<<'\n';
/*int cnt=0;
for(int i=1;i<=n;i++){
if(ind[i]==1)cnt++;
}
int ans=1;
for(int i=1;i<=cnt;i+=2){
ans=(ans*i)%mod;
}
cout<<ans<<'\n';
*/
}
return 0;
}

浙公网安备 33010602011771号