Codeforces Round #382 (Div. 2)解题报告

来源:互联网 发布:php 调用外部网页模板 编辑:程序博客网 时间:2024/05/18 15:05

A.Ostap and Grasshopper

大力模拟题,然而lc233大佬居然tmd怀疑是不是一个环。。。哎想多了

题意都懒得讲了orz

B.Urbanization

题意:给你n个数字,让你选n1个数字放到A集合,n2个数字放到B集合,让两个集合各自的平均数  加起来最大

我们强制要求n1<n2

一个数字t放入A堆答案的贡献是t/n1,所以排一遍序后,前n1个数字放入A集合

同理n1+1~n1+n2个数字放入B集合

大力算一发即可

#include <iostream>#include <cstdio>#include <cmath>#include <algorithm>#include <queue>#include <string>#include <map>#include <cstring>#include <ctime>#include <vector>#define inf 1e9#define ll long long#define For(i,j,k) for(int i=j;i<=k;i++)#define Dow(i,j,k) for(int i=k;i>=j;i--)using namespace std;inline void read(int &tx){   ll x=0,f=1;char ch=getchar();   while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}  while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}  tx=x*f; }inline void write(ll x){    if (x<0) putchar('-'),x=-x; if (x>=10) write(x/10);   putchar(x%10+'0');  }inline void writeln(ll x){write(x);puts("");}using namespace std;int n,n1,n2,a[400001];double ans;inline bool cmp(int x,int y){return x>y;}int main(){scanf("%d%d%d",&n,&n1,&n2);if(n1>n2)swap(n1,n2);For(i,1,n)scanf("%d",&a[i]);sort(a+1,a+n+1,cmp);For(i,1,n1)ans+=(double)a[i]/n1;For(i,n1+1,n1+n2)ans+=(double)a[i]/n2;printf("%.8lf",ans);}     

C.Tennis Championship

题意:n个人参加比赛,要求除第一次以外每次比赛的双方参加比赛次数不同,问至少多少次能得出冠军

既然要最少,那么在场的所有人参加比赛次数相差不大于1。

一个显然的结论,如果场上有x个参加t场,y个参加t-1场,则可以得到x-y个t+1场

例如5个参加t场,3个参加t-1场,则可以得到2个参加t+1场

那么我们倒推过来

显然就是个斐波那契啊。。。。。。

于是暴力推

#include <iostream>#include <cstdio>#include <cmath>#include <algorithm>#include <queue>#include <string>#include <map>#include <cstring>#include <ctime>#include <vector>#define inf 1e9#define ll long long#define For(i,j,k) for(int i=j;i<=k;i++)#define Dow(i,j,k) for(int i=k;i>=j;i--)using namespace std;inline void read(int &tx){   ll x=0,f=1;char ch=getchar();   while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}  while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}  tx=x*f; }inline void write(ll x){    if (x<0) putchar('-'),x=-x; if (x>=10) write(x/10);   putchar(x%10+'0');  }inline void writeln(ll x){write(x);puts("");}using namespace std;ll n,f[10001],tot;int main(){scanf("%lld",&n);f[0]=1;f[1]=1;tot=1;while(1){if(f[tot]>=n)break;tot++;f[tot]=f[tot-1]+f[tot-2];}if(f[tot]>n)tot--;printf("%lld",tot-1);}
D.Taxes

题意:给定一个n,定义f(n)为n的最大因子(除自己),把n分成任意份,求sigma(f(ni))的最小值

lc233大佬太强了orz

当我还在懵比时,大佬直接来了一句  哥德巴赫猜想啊

????

还有这种破题????

一个不等于2的偶数,分成两个质数,答案=2

对于一个是质数的奇数  答案=1

一个不是质数的奇数,我们分出一个2后,如果是质数了,答案=2,否则答案=3

鬼题。

#include <iostream>#include <cstdio>#include <cmath>#include <algorithm>#include <queue>#include <string>#include <map>#include <cstring>#include <ctime>#include <vector>#define inf 1e9#define ll long long#define For(i,j,k) for(int i=j;i<=k;i++)#define Dow(i,j,k) for(int i=k;i>=j;i--)using namespace std;inline void read(int &tx){   ll x=0,f=1;char ch=getchar();   while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}  while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}  tx=x*f; }inline void write(ll x){    if (x<0) putchar('-'),x=-x; if (x>=10) write(x/10);   putchar(x%10+'0');  }inline void writeln(ll x){write(x);puts("");}using namespace std;lln;int main(){scanf("%lld",&n);if(n==2){puts("1");return 0;}if(n%2==0){puts("2");return 0;}bool flag=1;For(i,2,sqrt(n)+1)if(n%i==0)flag=0;if(flag==1){puts("1");return 0;}n-=2;flag=1;For(i,2,sqrt(n)+1)if(n%i==0)flag=0;if(flag==1){puts("2");return 0;}puts("3");}     
E.Ostap and Tree

题意:给定一棵树,可以把任意个节点标记,要求所有节点都可以以小于k的距离到达一个被标记的节点,求标记的方案数


拿到题一脸懵逼

哎,到了E题果然就是不水了啊


还是看了题解,感觉有点类似于点分的树型dp吧

定义f[i][j]为距离i点,最近被标记点的距离是j的方案数


听起来很可做啊。。

对于节点x,我们每次枚举一个son[x]

然后考虑转移

我们要把f[son[x]][t]转移到f[x][j]的话,相当于是在另外的son[x]中选一个位置,然后来转移,因此是不相干的选法,显然乘法原理


然后我们分两类讨论 

1、(t+1)+x<=2*k

那么对于i来说,最近的被标记点为min(t+1,x)

2、(t+1)+x>2*k

这种情况下,属于不合法的一个状态,因此其实我们不能认为他是min(i+1,x),而是max(i+1,x)

这个我一开始也不是很理解,后来才发现:对于f[i][j] j>k,其实都是不合法的状态

为什么要记录呢?其实也很显然

因为我们转移类似1,2*k-1这种情况时,其实是需要用到的

这样写可以理解为是懒得开别的数字来存储不合法状态

如果不理解的话,可以画一下图

#include <iostream>#include <cstdio>#include <cmath>#include <algorithm>#include <queue>#include <string>#include <map>#include <cstring>#include <ctime>#include <vector>#define inf 1e9#define ll long long#define For(i,j,k) for(ll i=j;i<=k;i++)#define Dow(i,j,k) for(ll i=k;i>=j;i--)using namespace std;inline void read(ll &tx){   ll x=0,f=1;char ch=getchar();   while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}  while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}  tx=x*f; }inline void write(ll x){    if (x<0) putchar('-'),x=-x; if (x>=10) write(x/10);   putchar(x%10+'0');  }inline void writeln(ll x){write(x);puts("");}using namespace std;ll mo=1e9+7;ll poi[10001],F[10001],nxt[10001],f[1001][1001],tmp[1001],ans,n,k,x,y,cnt;bool vis[1001];inline void add(ll x,ll y){poi[++cnt]=y;nxt[cnt]=F[x];F[x]=cnt;}inline void dfs(ll x){vis[x]=1;f[x][0]=f[x][k+1]=1;for(ll i=F[x];i;i=nxt[i]){ll ne=poi[i];if(vis[ne])continue;dfs(ne);For(j,0,2*k+1)tmp[j]=0;For(j,0,2*k+1)For(t,0,2*k){if(j+t<=2*k)tmp[min(j,t+1)]+=f[x][j]*f[ne][t],tmp[min(j,t+1)]%=mo;elsetmp[max(j,t+1)]+=f[x][j]*f[ne][t],tmp[max(j,t+1)]%=mo;}For(j,0,2*k+1)f[x][j]=tmp[j];}}int  main(){read(n);read(k);For(i,1,n-1)read(x),read(y),add(x,y),add(y,x);dfs(1);For(i,0,k)ans+=f[1][i],ans%=mo;writeln(ans);}


 
阅读全文
1 0