由于个人真的菜,所以我没打秦皇岛,只有一个威海打星名额,上星期跟着队友做志愿者,实则在隔壁房间摸鱼读题,这两天有时间就认真做了做,K题的树型dp让我现场写肯定是写不出来的,所以我还看了别人的代码后做的。至于别的题,后面陆续有时间再做了 没时间也不要喷我QAQ
现在已经有人把题目上传到Gym 102769了,有兴趣可以自己去搜一下
A.Greeting from Qinhuangdao
传送门
题意:r个红球,b个蓝球,问连续两次取出红球的概率,以最简分式形式输出
题意:特判概率为0和1,
a
÷
(
a
+
b
)
×
(
a
−
1
)
÷
(
a
−
1
+
b
)
a\div(a+b)\times(a-1)\div(a-1+b)
a÷(a+b)×(a−1)÷(a−1+b),取出gcd(分子,分母),后化简即可
#pragma GCC optimize(2)
#include<bits/stdc++.h>
using namespace std;
#define AC 0
#define Please return
#define endl "\n"
#define ll long long
int main(){
ios_base::sync_with_stdio(0);cin.tie(0),cout.tie(0);
int _,cas=1;cin>>_;
while(_--){
ll r,b;cin>>r>>b;
cout<<"Case #"<<cas++<<": ";
if(r<2)cout<<"0/1";
else if(b==0)cout<<"1/1";
else {
ll fir=r*(r-1),sec=(r+b)*(r+b-1),gcd=__gcd(fir,sec);
cout<<fir/gcd<<"/"<<sec/gcd;
}
cout<<endl;
}
Please AC;
}
E.Exam Results
题意:n个人,每个的成绩有两种可能,分别是 a i a_i ai和 b i b_i bi,合格线是这n个人中成绩最高的人乘以p%,问最多能有多少个人合格。
#pragma GCC optimize(2)
#include<bits/stdc++.h>
using namespace std;
#define AC 0
#define Please return
#define endl "\n"
#define ll long long
const int MAX=4e5+7; //注意范围
struct node{
int val,pos;
}a[MAX];
int b[MAX],c[MAX];
bool cmp(node a,node b){
return a.val==b.val?a.pos<b.pos:a.val>b.val;
}
int main(){
ios_base::sync_with_stdio(0);cin.tie(0),cout.tie(0);
int _,cas=1;cin>>_;
while(_--){
cout<<"Case #"<<cas++<<": ";
ll n,p;cin>>n>>p;
for(int i=1;i<=n;i++)b[i]=c[i]=0;
for(int i=1;i<=n;i++){
cin>>a[2*i-1].val; a[2*i-1].pos=i;
cin>>a[2*i].val; a[2*i].pos=i;
}
sort(a+1,a+2*n+1,cmp);
int cnt=0,res=0,pos1=0,pos2=0,ans=0;
for(int i=1;i<=n;i++){
while((pos1+1)<=2*n&&cnt<n){
b[a[++pos1].pos]++;//前n个人每个位置出现的次数
if (b[a[pos1].pos]==1) cnt++; //出现一次记录
}
while((pos2+1)<=2*n&&a[pos2+1].val>=((1ll*a[i].val*p%100==0)?(1ll*a[i].val*p/100):(1ll*a[i].val*p/100 +1))){
c[a[++pos2].pos]++;//及格的
if (c[a[pos2].pos] == 1) res++; //出现一次记录
}
if (cnt == n) ans = max(ans, res);
b[a[i].pos]--;//除去当前值
if (b[a[i].pos] == 0) cnt--;
c[a[i].pos]--;
if (c[a[i].pos] == 0) res--;
}
cout<<ans<<endl;
}
Please AC;
}
F.Friendly Group
题意:n个人中m个关系,每次可任意组合k人去参加会议(0<=k<=n),且可知友谊值=k人中存在的关系数-k。
通俗的理解就是n个点中有m条边,选出任意点组成连通块中边数-点数最大值和为多少
题解:dfs或者并查集维护连通块的点数和边数,
∑
每
个
连
通
块
\sum_{每个连通块}
∑每个连通块边数-点数>0的值 注意别用map记录连通块,因为容易炸
#pragma GCC optimize(2)
#include<bits/stdc++.h>
using namespace std;
#define AC 0
#define Please return
#define endl "\n"
#define ll long long
const int MAX=3e5+7;
int pre[MAX],n,m;
int nv[MAX],nl[MAX];
void init(){
for(int i=1;i<=n;i++)pre[i]=i,nv[i]=1,nl[i]=0;
}
int Find(int x){
return pre[x]==x?x:pre[x]=Find(pre[x]);
}
int main(){
ios_base::sync_with_stdio(0);cin.tie(0),cout.tie(0);
int _,cas=1;cin>>_;
while(_--){
n,m;cin>>n>>m;
init();
cout<<"Case #"<<cas++<<": ";
for(int i=0;i<m;i++){
int x,y;cin>>x>>y;
int fx=Find(x),fy=Find(y);
if(fx!=fy){
pre[fy]=fx;
nv[fx]+=nv[fy];
nl[fx]+=nl[fy];
nl[fx]++;
}
else nl[fx]++;
}
ll ans=0;
for(int i=1;i<=n;i++)
if(nv[i]>=2)ans+=max(0,nl[i]-nv[i]);
cout<<ans<<endl;
}
Please AC;
}
G.Good Number
题意:输入一个n和k,问1-n中有多少个开了k次根后还可以整除它本身。
题解:注意题目给的数据范围是
1
1
1~
1
0
9
10^9
109,
2
30
2^{30}
230=1,073,741,824,所以保险可以见最多只能去到
2
31
2^{31}
231,k≥31后,开k次根都是得到1,1可以除以任何正整数,故有n个满足
然后从1开始暴力判断k次方且满住小于n的数,再通过每段区间的数学规律,遍历求出结果即可。
#pragma GCC optimize(2)
#include<bits/stdc++.h>
using namespace std;
#define AC 0
#define Please return
#define endl "\n"
#define ll long long
ll qpow(ll a,ll b){
ll res=1;
for(;b;b>>=1){
if(b&1)res=a*res;
a*=a;
}
return res;
}
int main(){
ios_base::sync_with_stdio(0);cin.tie(0),cout.tie(0);
int _,cas=1;cin>>_;
while(_--){
ll n,k;cin>>n>>k;
cout<<"Case #"<<cas++<<": ";
if(k>=31||k==1)cout<<n;
else {
vector<ll>p; p.push_back(0);
for(int i=1;i<=n;i++){
ll x=qpow(i,k);
if(x>n)break;
p.push_back(x);
}
ll ans=0;
for(int i=2;i<p.size();i++)
ans+=(p[i]-1-p[i-1])/(i-1)+1;
if(p.back()==n)ans++;
else ans+=(n-p.back())/(p.size()-1)+1;
cout<<ans;
}
cout<<endl;
}
Please AC;
}
K.Kingdom’s Power
题意:王国在1节点且该点为树的根节点,每天最多出动一个军队,每个军队每天最多在相邻的边移动一次,问最少需要多少天可以遍历完所有的城市
题解:类树形dp,对于每个点都维护以该节点为根节点的子树
#pragma GCC optimize(2)
#include<bits/stdc++.h>
using namespace std;
#define AC 0
#define Please return
#define endl "\n"
#define ll long long
const int MAX=2e6+7; //注意范围
struct node{
ll a,maxdep,ans;
}dp[MAX];
struct Edge{
int to,next;
}edge[MAX];
int n,head[MAX],dep[MAX],cnt=0;
void add_edge(int u,int v){
edge[++cnt]={v,head[u]};head[u]=cnt;
edge[++cnt]={u,head[v]};head[v]=cnt;
}
void dfs(int u,int fa){
node mx={0,0,0};
dp[u]={1,dep[u],0};
int mxn=0,suma=0,son=0;
for(int i=head[u];i;i=edge[i].next){
int v=edge[i].to;
if(v==fa)continue;
son++; dep[v]=dep[u]+1;
dfs(v,u);
dp[u].maxdep=max(dp[u].maxdep,dp[v].maxdep);
if(dp[v].maxdep>mx.maxdep)mx=dp[v],mxn=v;
}
ll sum=0;
for(int i=head[u];i;i=edge[i].next){
int v=edge[i].to;
if(v==fa||v==mxn)continue; //排除父节点和最长链
sum+=dp[v].ans+dp[v].a;
suma+=dp[v].a;
if(dp[v].maxdep-dep[u]<dep[u]-dep[1]){
sum+=dp[v].maxdep-dep[u]; suma--;
}
}
if(son==0)return ;
sum+=dp[mxn].a+dp[mxn].ans;
suma+=dp[mxn].a;
if(dp[mxn].maxdep-dep[u]<dep[u]-dep[1]) suma--;
if(suma==0)suma=1;
dp[u].a=suma; dp[u].ans=sum;
}
int main(){
ios_base::sync_with_stdio(0);cin.tie(0),cout.tie(0);
int _,cas=1;cin>>_;
while(_--){
cin>>n;
cnt=0;
for(int i=0;i<=n;i++)head[i]=0;
cout<<"Case #"<<cas++<<": ";
for(int i=2;i<=n;i++){
int v;cin>>v;
add_edge(v,i);
}
dep[1]=0;
dfs(1,1);
cout<<dp[1].ans<<endl;
}
Please AC;
}