AtCoder Regular Contest 096


C - Many Medians

题意:

有A,B两种匹萨和三种购买方案,买一个A,买一个B,买半个A和半个B,花费分别为a,b,c。

求买X个A和Y个B最小花费使多少。

分析:

明显的发现肯定买性价比更高的方案,分情况讨论一下,如果\(a+b<=2*c\),那么明显的先买足c到A,B中较小的一个,然后再比较一下剩下的那个的单价和\(2*c\)的大小。

  1. A[ans=] -->|a+b<=2*c| B(A*a+B*b)
  2. A --> |else| C{2*c}
  3. C --> |A<=B| D[*A]
  4. C --> |else| E[*B]
  5. D --> |b<=2*c| F[+b*B-b*A]
  6. D --> |else| G[+2*c*B-2*c*A]
  7. E --> |a<=2*c| H[+a*A-a*B]
  8. E --> |else| I[+2*c*A-2*c*B]
  1. #include <iostream>
  2. #include <cmath>
  3. #include <string>
  4. #include <cstring>
  5. #include <cstdio>
  6. #include <algorithm>
  7. #define re register
  8. #define max(a,b) ((a)>(b)?(a):(b))
  9. #define min(a,b) ((a)<(b)?(a):(b))
  10. #define MAXN 4000007
  11. #define mo 19930726
  12. #define ll long long
  13. using namespace std;
  14. typedef unsigned long long ull;
  15. #define ms(arr) memset(arr, 0, sizeof(arr))
  16. const int inf = 0x3f3f3f3f;
  17. ll a,b,c,x,y,ans;
  18. int main()
  19. {
  20. cin>>a>>b>>c>>x>>y;
  21. ll minn=min(x,y);
  22. if(a+b<=2*c){
  23. cout<<x*a+y*b;
  24. } else {
  25. ans+=minn*c*2;
  26. if(x<y){
  27. if(2*c<=b) b=2*c;
  28. ans+=b*(y-x);
  29. } else {
  30. if(2*c<=a) a=2*c;
  31. ans+=a*(x-y);
  32. }
  33. cout<<ans;
  34. }
  35. }

D - Static Sushi

题意:

有n个寿司围成一圈,给出寿司离起点的距离v和寿司的价值x,从起点开始走,任意时刻都可以决定走的方向,并且可以在任意时刻停下,求\(max(\sum x-\sum v)\)。

分析:

可以考虑我们一共有几种选择,可以发现最优的情况一定是向一个方向走然后掉头走另一个方向。前缀和求一下,顺时针逆时针直接搞搞也就出来了。

  1. #include <iostream>
  2. #include <cmath>
  3. #include <string>
  4. #include <cstring>
  5. #include <cstdio>
  6. #include <algorithm>
  7. #define re register
  8. #define max(a,b) ((a)>(b)?(a):(b))
  9. #define min(a,b) ((a)<(b)?(a):(b))
  10. #define MAXN 200007
  11. #define mo 19930726
  12. using namespace std;
  13. typedef unsigned long long ull;
  14. #define ms(arr) memset(arr, 0, sizeof(arr))
  15. #define ll long long
  16. const int inf = 0x3f3f3f3f;
  17. ll n,v[MAXN],x[MAXN],C,sum[MAXN],pre[MAXN],ans;
  18. int main()
  19. {
  20. cin>>n>>C;
  21. for(int i=1;i<=n;i++){
  22. cin>>x[i]>>v[i];
  23. sum[i]=sum[i-1]+v[i];
  24. pre[i]=max(pre[i-1],sum[i]-x[i]);
  25. }
  26. ll cnt=0;
  27. ll c=C;
  28. for(int i=n;i>=1;i--){
  29. ans=max(ans,cnt+pre[i]);
  30. cnt+=v[i]-2*(c-x[i]);
  31. c=x[i];
  32. }
  33. for(int i=1;i<=n;i++) x[i]=C-x[i];
  34. reverse(x+1,x+n+1);
  35. reverse(v+1,v+n+1);
  36. for(int i=1;i<=n;i++){
  37. sum[i]=sum[i-1]+v[i];
  38. pre[i]=max(pre[i-1],sum[i]-x[i]);
  39. }
  40. cnt=0;
  41. c=C;
  42. for(int i=n;i>=1;i--){
  43. ans=max(ans,cnt+pre[i]);
  44. cnt+=v[i]-2*(c-x[i]);
  45. c=x[i];
  46. }
  47. cout<<ans;
  48. }

E - Everything on It

题意:

给你n种酱,可以任意添加入拉面中。你可以有任意碗拉面,然后你可以选择加入和不加这n种酱的任意一种进去任意一碗拉面中,问你怎么添加,使得:

1.这任意碗拉面中,不存在两碗拉面加的酱相同。

2.这任意碗拉面中,每一种酱都至少加入过两碗拉面中。

满足以上两个条件的加酱方法算一种方案。问有多少种方案%mod。

分析:

不难看出这题应该是一个容斥。

我们不犯设\(f[i]\)为有i种酱不合条件时的方案数,那么明显可以求出答案是\(\sum_{i=0}^n (-1)^if[i]C_n^i\)。

那么明显我们只需要求出\(f\)就可以轻松得到ans。

建立另一个数组\(g[i][j]\)表示前j碗拉面中有i种酱不符合条件的方案数。我们可以用类第二类斯特林数的方式求出来,\(g[i][j]=g[i-1][j-1]+g[i-1][j]*(j+1)\)。

可以这么想,当我们递推过来时,如果前\(i-1\)种酱在\(j-1\)碗面中,那么第\(i\)种酱一定在第\(j\)碗面中。如果前\(i-1\)种酱在前\(j\)碗面中,那么第\(i\)种酱就可在任何一碗面中或者压根就不在任何一碗面中。

之后求出\(f[i]=\sum_{j=0}^ig[i][j]2^{(n-i)j} 2^{2^{(n-i)}}\)

然后用这个公式

\(a^n \equiv a^{n\cdot mod(p-1)}(modp)\)

再直接往\(\sum_{i=0}^n (-1)^if[i]C_n^i\)这东西里面套就行了。

  1. #include <cstring>
  2. #include <cstdio>
  3. #include <algorithm>
  4. #include <queue>
  5. #include <iostream>
  6. #define re register
  7. #define max(a,b) ((a)>(b)?(a):(b))
  8. #define min(a,b) ((a)<(b)?(a):(b))
  9. #define MAXN 3007
  10. #define ll long long
  11. using namespace std;
  12. typedef unsigned long long ull;
  13. #define ms(arr) memset(arr, 0, sizeof(arr))
  14. const int inf = 0x3f3f3f3f;
  15. ll c[MAXN][MAXN];
  16. ll g[MAXN][MAXN];
  17. ll n,mo;
  18. inline ll niubide_power(ll k,ll x,ll mod)
  19. {
  20. ll ans=1;
  21. while(x) {
  22. if(x&1ll) ans=ans*k%mod;
  23. k=(k*k%mod);
  24. x>>=1;
  25. }
  26. return ans;
  27. }
  28. int main()
  29. {
  30. cin>>n>>mo;
  31. for(re int i=1;i<=n;i++){
  32. c[i][0]=1;c[i][i]=1;
  33. for(int j=1;j<i;j++)
  34. c[i][j]=(c[i-1][j-1]+c[i-1][j])%mo;
  35. }
  36. for(int i=0;i<=n;i++){
  37. g[i][0]=1;
  38. for(int j=1;j<=i;j++)
  39. g[i][j]=(g[i-1][j-1]+g[i-1][j]*(j+1)%mo)%mo;
  40. }
  41. ll ans=0;
  42. for(int i=0;i<=n;i++){
  43. ll k=c[n][i];
  44. if(i&1) k=(mo-k)%mo;
  45. ll kind=niubide_power(2,n-i,mo);
  46. ll x=niubide_power(2,n-i,mo-1);
  47. x=niubide_power(2,x,mo);
  48. ll cnt=0,y=1;
  49. for(int j=0;j<=i;j++){
  50. cnt=(cnt+(g[i][j]*y)%mo)%mo;
  51. y=kind*y%mo;
  52. }
  53. ans=(ans+(k*cnt)%mo*x%mo)%mo;
  54. }
  55. cout<<ans;
  56. }

F - Sweet Alchemy

题意:

\(n≤50\) 的树,每个点有权值,现要选点(可多次选一个点)使点数尽量多,如下限制:

选的总权值不超过\(C≤1e9\);\(c_i\) 表示\(i\)选的次数,\(p_i\) 表示 \(i\) 的父亲,那么\(c_{p[i]}≤c_i≤c_{p[i]}+D\)

\(D≤1e9\)是给定常数。

分析:

首先我们可以差分一下这棵树,然后这个题就变成了:在一棵树上有不超过50 个节点,每个节点均有一个权值及一个代价,除1号节点外每个节点选择的次数均不能超过 D。求在总代价不超过x的前提下,如何使权值最大化?

看上去像是一个经典的背包问题,但是超大的背包容量你也背不起来。

突破口貌似是\(n\le50\)这极少的物品个数。

但是突破不了了。

看了题解觉得真是非常神仙。

首先背包问题有一个经典错解,就是那个性价比高选哪个,但是明显错误的就是这样可能会造成包内有大量剩余空间没得使用浪费掉,但实际上是有更优秀的解的。

考虑什么时候我们能用性价比更高的物品替换到性价比低的。假设我们有\(v_i\),\(w_i\)和\(v_j\),\(w_j\),且\(\frac{v_i}{w_i}>\frac{v_j}{w_j}\)。那么我们在选了\(v_i\)个\(j\)物品,就相当于选了\(v_j\)个\(i\)物品。因为权值没有变化,但是代价却更小了。

所以我们不能直接替换的最多只有\(v_i-1\)这么多,而\(v\)的足够小的范围是可以接受的。所以直接把每件物品都取\(min(D,n)\)件然后多重背包就可以了。

  1. #include <iostream>
  2. #include <cstring>
  3. #include <cstdio>
  4. #include <algorithm>
  5. #define re register
  6. #define MAXN 507
  7. #define mo 19930726
  8. #define ll long long
  9. #define int ll
  10. using namespace std;
  11. typedef unsigned long long ull;
  12. #define ms(arr) memset(arr, 0, sizeof(arr))
  13. const int inf = 0x3f3f3f3f;
  14. int n,X,D,ans,num,dp[125500];
  15. int w[MAXN],val[MAXN],pos[MAXN],head[MAXN];
  16. int tot,V[MAXN*MAXN],W[MAXN*MAXN],cnt;
  17. struct po
  18. {
  19. int nxt,to;
  20. }edge[MAXN<<1];
  21. int read()
  22. {
  23. int x=0,f=1;char ch=getchar();
  24. while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
  25. while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
  26. return x*f;
  27. }
  28. inline void add_edge(int from,int to)
  29. {
  30. edge[++num].nxt=head[from];
  31. edge[num].to=to;
  32. head[from]=num;
  33. }
  34. void dfs(int u)
  35. {
  36. val[u]=1;
  37. for(int i=head[u];i;i=edge[i].nxt){
  38. int v=edge[i].to;
  39. dfs(v);
  40. w[u]+=w[v];val[u]+=val[v];
  41. }
  42. cnt+=val[u]*n; pos[u]=u;
  43. }
  44. inline bool cmp(int x,int y){return val[x]*w[y]>val[y]*w[x];}
  45. main()
  46. {
  47. n=read();X=read();D=read();
  48. w[1]=read();
  49. for(re int i=2;i<=n;i++){
  50. w[i]=read();int x=read();
  51. add_edge(x,i);
  52. }
  53. dfs(1);
  54. sort(pos+1,pos+n+1,cmp);
  55. int tmp=min(n,D);
  56. for(re int i=1;i<=cnt;i++) dp[i]=inf;
  57. for(re int i=1;i<=n;i++){
  58. int len=1,lim=tmp;
  59. while(lim>=len){
  60. V[++tot]=len*val[pos[i]];
  61. W[tot]=len*w[pos[i]];
  62. lim-=len,len<<=1;
  63. }
  64. if(lim) V[++tot]=lim*val[pos[i]],W[tot]=lim*w[pos[i]];
  65. }
  66. for(int i=1;i<=tot;i++)
  67. for(int j=cnt;~j;j--){
  68. if(j>=V[i]) dp[j]=min(dp[j],dp[j-V[i]]+W[i]);
  69. }
  70. int ans=0;
  71. for(int i=0;i<=cnt;i++){
  72. if(dp[i]>X) continue;
  73. int ret=i,left=X-dp[i];
  74. for(int j=1;j<=n;j++){
  75. int tem=pos[j],used=min(max(D-n,0ll),left/w[tem]);
  76. if(tem==1) used=left/w[tem];
  77. left-=w[tem]*used;
  78. ret+=val[tem]*used;
  79. }
  80. ans=max(ans,ret);
  81. }
  82. cout<<ans;
  83. }

AtCoder Regular Contest 096的更多相关文章

  1. [AtCoder Regular Contest 096 E] Everything on It 解题报告 (第二类斯特林数+容斥原理)

    题目链接:https://arc096.contest.atcoder.jp/tasks/arc096_c Time limit : 4sec / Memory limit : 512MB Score ...

  2. Atcoder Regular Contest 096 D - Sweet Alchemy(贪心+多重背包)

    洛谷题面传送门 & Atcoder 题面传送门 由于再过 1h 就是 NOI 笔试了所以题解写得会略有点简略. 考虑差分,记 \(b_i=c_i-c_{fa_i}\),那么根据题意有 \(b_ ...

  3. Atcoder Regular Contest 096 C - Everything on It(组合数学)

    Atcoder 题面传送门 & 洛谷题面传送门 简单题,由于这场 arc 的 F 是 jxd 作业而我不会做,所以只好来把这场的 E 水掉了. 我们记 \(f(i)\) 为钦定 \(i\) 个 ...

  4. AtCoder Regular Contest 096 D - Static Sushi(线性dp)

    Problem Statement "Teishi-zushi", a Japanese restaurant, is a plain restaurant with only o ...

  5. AtCoder Regular Contest 061

    AtCoder Regular Contest 061 C.Many Formulas 题意 给长度不超过\(10\)且由\(0\)到\(9\)数字组成的串S. 可以在两数字间放\(+\)号. 求所有 ...

  6. AtCoder Regular Contest 094 (ARC094) CDE题解

    原文链接http://www.cnblogs.com/zhouzhendong/p/8735114.html $AtCoder\ Regular\ Contest\ 094(ARC094)\ CDE$ ...

  7. AtCoder Regular Contest 092

    AtCoder Regular Contest 092 C - 2D Plane 2N Points 题意: 二维平面上给了\(2N\)个点,其中\(N\)个是\(A\)类点,\(N\)个是\(B\) ...

  8. AtCoder Regular Contest 093

    AtCoder Regular Contest 093 C - Traveling Plan 题意: 给定n个点,求出删去i号点时,按顺序从起点到一号点走到n号点最后回到起点所走的路程是多少. \(n ...

  9. AtCoder Regular Contest 094

    AtCoder Regular Contest 094 C - Same Integers 题意: 给定\(a,b,c\)三个数,可以进行两个操作:1.把一个数+2:2.把任意两个数+1.求最少需要几 ...

随机推荐

  1. 61、常规控件(4)TabLayout-便捷实现标签

    <android.support.design.widget.TabLayout android:id="@+id/tabs" android:layout_width=&q ...

  2. DotNet软件开发框架

    这是我4月份发在donews博客上的文章,现在都转到博客园来,风满袖希望进一步阐述你的架构,我就将这篇文章转移到博客园.原文:http://blog.donews.com/shanyou/archiv ...

  3. [.NET网格计算框架] Alchemi

      Alchemi [.NET网格计算框架] 是 一个以使用简易为目的的Windows下的网格计算框架.它提供了:a)开发网格软件的编程环境 和 b)建造网格和运行网格软件的运行机制.       A ...

  4. hdu2732 (Leapin' Lizards)

    题目链接:传送门 题目大意:给你 n,m  n:有几行图,m是一个人最多跳m个曼哈顿距离. 给你两张图,第一张图数字为0表示没有柱子,否则有柱子且只能跳出去 x 次(x为当前字符代表的数字) 第二张图 ...

  5. Canvas-三角函数曲线图

    以本图为例,要做这张图,需要一些数学知识(三角函数sin,cos),有canvas的基础知识 Html <!DOCTYPE html> <html> <head> ...

  6. 【文章阅读】详解MySQL数据类型

    详解MySQL数据类型 - 五月的仓颉 - 博客园 http://www.cnblogs.com/xrq730/p/8446246.html 注:对于MySQL的数据类型做了详细的讲解,这是我看过的最 ...

  7. python系列十六:Python3 面向对象

    #!/usr/bin/python #-*-coding:gbk-*- #Python3 面向对象 '''面向对象技术简介    类(Class): 用来描述具有相同的属性和方法的对象的集合.它定义了 ...

  8. SpringMVC 返回的 json 中去除某些不必要的属性

    修改返回的Model,在对应的属性的get方法上使用 com.fasterxml.jackson.annotation.JsonIgnore 注解即可. 如 @JsonIgnore(true) pub ...

  9. Cisco路由器DHCP配置浅析

    enable  config terminal (进入配置模式)  ip dhcp pool global(配置一个根地址池,global是地址池的名称,你可以采用有意义的字符串来表示) config ...

  10. 深入理解Redis主键失效原理及实现机制(转)

    原文:深入理解Redis主键失效原理及实现机制 作为一种定期清理无效数据的重要机制,主键失效存在于大多数缓存系统中,Redis 也不例外.在 Redis 提供的诸多命令中,EXPIRE.EXPIREA ...