[矩阵树定理 容斥 meet in middle] Topcoder SRM 551 DIV1 Hard. SweetFruits

Topcoder SRM551 Div 1 1000:SweetFruits(矩阵树+容斥) 题解: 考虑枚举哪几个水果是甜的。 发现如果枚举的数量一样,那么对答案的贡献也一样。那么可以根据枚举数量来一起处理。 枚举完数量kkk之后,甜与半甜的不连边,然后跑矩阵树,得到小等于kkk的甜的水果的生成树数量。 因为之前的已经处理过,直接减掉就好。 注意减去的时候要减去组合数,因为这k个中任意组合都会被统计。 之后问题变为了数量kkk, 值小等于vvv的个数,这个直接折半就行了。 ... 阅读详情

枚举最后的树中有多少个是truly sweet的
答案就是

∑i=0nfi×gi

其中,fi 表示选出 i 个水果使其价值和不超过Limit的方案数
gi 是有 i 个truly sweet的生成树个数

fi 可以meet in middle
设图中前 i 个点是truly sweet, i+1 到 k 是sweet的
truly sweet之间两两连边,不甜的水果两两连边,不甜的水果和甜的水果连边

跑矩阵树定理可以得到truly sweet数量之多为 i 的方案数

容斥一下就得到了 gi

// BEGIN CUT HERE  

// END CUT HERE  
#include <vector>  
#include <list>  
#include <map>  
#include <set>  
#include <deque>  
#include <stack>  
#include <bitset>  
#include <algorithm>  
#include <functional>  
#include <numeric>  
#include <utility>  
#include <sstream>  
#include <iostream>  
#include <iomanip>  
#include <cstdio>  
#include <cmath>  
#include <cstdlib>  
#include <ctime>  
#include <queue>
#include <assert.h>
#include <cstring>  
#define pb push_back

using namespace std;  

const int N=105,P=1e9+7;

int n,lim,a[N],f[N],g[N];

vector<int> s,A[N],B[N];

void dfs(int x,int n,int num,int v,vector<int> C[]){
  if(v>lim) return ;
  if(x>=n) return C[num].pb(v);
  dfs(x+1,n,num+1,v+s[x],C);
  dfs(x+1,n,num,v,C);
}

int cnt;

inline void part1(){
  for(int i=0;i<=n;i++) A[i].clear(),B[i].clear();
  dfs(0,cnt/2,0,0,A);
  dfs(cnt/2,cnt,0,0,B);
  for(int i=0;i<=n;i++) if(A[i].size()) sort(A[i].begin(),A[i].end());
  for(int i=0;i<=n;i++) if(B[i].size()) sort(B[i].begin(),B[i].end());
  for(int i=0;i<=n;i++){
    if(!A[i].size()) continue;
    for(int j=0;j<=n;j++){
      if(!B[j].size()) continue;
      int p=0;
      for(int k=B[j].size()-1;~k;k--){
    while(p<A[i].size() && A[i][p]+B[j][k]<=lim) p++;
    (f[i+j]+=p)%=P;
      }
    }
  }
}

typedef int Mat[N][N];

int inv[N],fac[N];

inline int Pow(int x,int y){
  int ret=1;
  for(;y;y>>=1,x=1LL*x*x%P) if(y&1) ret=1LL*ret*x%P;
  return ret;
}

inline int det(Mat a){
  int sp=0;
  for(int i=1;i<n;i++){
    int p; for(p=i;!a[p][i] && p<n;p++);
    if(p==n) return 0;
    if(p!=i){
      for(int j=1;j<n;j++) swap(a[i][j],a[p][j]);
      sp^=1;
    }
    for(int j=i+1;j<n;j++)
      if(a[j][i]){
    int t=1LL*a[j][i]*Pow(a[i][i],P-2)%P;
    for(int k=1;k<n;k++)
      a[j][k]=(a[j][k]+P-1LL*t*a[i][k]%P)%P;
      }
  }
  int ret=1; for(int i=1;i<n;i++) ret=1LL*ret*a[i][i]%P;
  if(sp) ret=-ret;
  return (ret+P)%P;
}

inline int calc(int x){
  static Mat tmp;
  memset(tmp,0,sizeof(tmp));
  for(int i=1;i<=n;i++)
    for(int j=i+1;j<=n;j++)
      if(i>cnt || j>cnt || (i<=x && j<=x)){
    tmp[i][j]=P-1; tmp[j][i]=P-1; tmp[i][i]++; tmp[j][j]++;
      }
  return det(tmp);
}

inline int C(int x,int y){
  return 1LL*fac[x]*inv[y]%P*inv[x-y]%P;
}

inline void part2(){
  for(int i=0;i<=cnt;i++) g[i]=calc(i);
  for(int i=1;i<=cnt;i++){
    for(int j=0;j<i;j++)
      g[i]=(g[i]-1LL*C(i,j)*g[j])%P;
    g[i]=(g[i]+P)%P;
  }
}

inline void Pre(){
  fac[0]=1; for(int i=1;i<=n;i++) fac[i]=1LL*fac[i-1]*i%P;
  inv[1]=1; for(int i=2;i<=n;i++) inv[i]=1LL*(P-P/i)*inv[P%i]%P;
  inv[0]=1; for(int i=1;i<=n;i++) inv[i]=1LL*inv[i]*inv[i-1]%P;
}

class SweetFruits{  
public:  
  int countTrees(vector <int> sweetness, int maxSweetness) {  
    n=sweetness.size(); lim=maxSweetness; Pre(); s.clear();
    for(int i=1;i<=n;i++){
      a[i]=sweetness[i-1];
      if(a[i]>=0) s.pb(a[i]);
    }
    cnt=s.size();
    memset(f,0,sizeof(f)); memset(g,0,sizeof(g));
    part1(); part2(); int ans=0;
    for(int i=0;i<=cnt;i++) ans=(ans+1LL*f[i]*g[i])%P;
    return ans;
  }


  // BEGIN CUT HERE
public:
  void run_test(int Case) { if ((Case == -1) || (Case == 0)) test_case_0(); if ((Case == -1) || (Case == 1)) test_case_1(); if ((Case == -1) || (Case == 2)) test_case_2(); if ((Case == -1) || (Case == 3)) test_case_3(); if ((Case == -1) || (Case == 4)) test_case_4(); }
private:
  template <typename T> string print_array(const vector<T> &V) { ostringstream os; os << "{ "; for (typename vector<T>::const_iterator iter = V.begin(); iter != V.end(); ++iter) os << '\"' << *iter << "\","; os << " }"; return os.str(); }
  void verify_case(int Case, const int &Expected, const int &Received) { cerr << "Test Case #" << Case << "..."; if (Expected == Received) cerr << "PASSED" << endl; else { cerr << "FAILED" << endl; cerr << "\tExpected: \"" << Expected << '\"' << endl; cerr << "\tReceived: \"" << Received << '\"' << endl; } }
  void test_case_0() { int Arr0[] = {1, 2, -1, 3}; vector <int> Arg0(Arr0, Arr0 + (sizeof(Arr0) / sizeof(Arr0[0]))); int Arg1 = 3; int Arg2 = 3; verify_case(0, Arg2, countTrees(Arg0, Arg1)); }
  void test_case_1() { int Arr0[] = {1, 2, -1, 3}; vector <int> Arg0(Arr0, Arr0 + (sizeof(Arr0) / sizeof(Arr0[0]))); int Arg1 = 5; int Arg2 = 7; verify_case(1, Arg2, countTrees(Arg0, Arg1)); }
  void test_case_2() { int Arr0[] = {-1, -1, 2, 5, 5}; vector <int> Arg0(Arr0, Arr0 + (sizeof(Arr0) / sizeof(Arr0[0]))); int Arg1 = 6; int Arg2 = 20; verify_case(2, Arg2, countTrees(Arg0, Arg1)); }
  void test_case_3() { int Arr0[] = {2, 6, 8, 4, 1, 10, -1, -1, -1, -1}; vector <int> Arg0(Arr0, Arr0 + (sizeof(Arr0) / sizeof(Arr0[0]))); int Arg1 = 15; int Arg2 = 17024000; verify_case(3, Arg2, countTrees(Arg0, Arg1)); }
  void test_case_4() { int Arr0[] = {1078451, -1, 21580110, 8284711, -1, 4202301, 3427559, 8261270, -1, 16176713,
                     22915672, 24495540, 19236, 5477666, 12280316, 3305896, 17917887, 564911, 22190488, 21843923,
                     23389728, 14641920, 9590140, 12909561, 20405638, 100184, 23336457, 12780498, 18859535, 23180993,
                     10278898, 5753075, 21250919, 17563422, 10934412, 22557980, 24895749, 7593671, 10834579, 5606562}; vector <int> Arg0(Arr0, Arr0 + (sizeof(Arr0) / sizeof(Arr0[0]))); int Arg1 = 245243285; int Arg2 = 47225123; verify_case(4, Arg2, countTrees(Arg0, Arg1)); }
  // END CUT HERE

};  

// BEGIN CUT HERE  
int main()  
{  
  SweetFruits ___test;
  ___test.run_test(4);
  system("pause");  
}  
// END CUT HERE  
百元DIY手机荧光计:低成本荧光检测平台搭建与实战 荧光检测是一种基于物质受特定波长光激发后发射更长波长荧光的分析技术,其核心原理在于光与物质的相互作用。通过选择性激发与检测,该技术能实现对痕量物质的高灵敏度、高特异性定量分析,在生物医学、环境监测和食品安全等领域具有重要价值。传统荧光分光光度计虽精度高,但成本昂贵、体积庞大且操作复杂,限制了其在现场快检和普及教育中的应用。本文聚焦于如何利用智能手机的高性能摄像头和处理器,结合低成本光学滤光片和LED光源,构建一个便携、经济的DIY荧光检测平台。该方案通过简化光路设计,采用带通滤光片进行波长选择,并利用图像处 阅读详情

相关推荐

macOS安装Cplex+yalmip

macOS安装Cplex+yalmip

DS 4248

[TopCoder 12141] SweetFruits(折半搜索 + 矩阵树定理) | 错题本

文章目录题目题目大意分析代码 题目 [TopCoder 12141] SweetFruits 题目大意 给出 n (n≤40)n\ (n \leq 40)n (n≤40) 个水果,每个水果可能是“甜”的或“不甜”的,每个甜的水果有一个甜度值,特别的,为了便于读入,输入中不甜的水果甜度值为 −1-1−1。现在要求将 nnn 个水果连成一棵树,这个树的甜度值为“真甜”的水果的甜度值之和。“真甜”的水果定义如下:若一个甜的水果与另外至少一个甜的水果通过一条边直接相连,那么这个水果是“真甜”的。

ixRic 525

FIFO Generate IP核使用——FIFO写操作详解及Status Flags页配置

本文介绍了FIFO的写操作及Status Flags页的配置信息。

u011565038的博客 2283

【矩阵树定理+容斥】Topcoder SRM 551 DIV1 Hard SweetFruits (TC12141)

【前言】 吐槽一下TC的交代码,在SRMs的练习模式那里交每提交一次分数上限会少一点,于是根本不知道过没过。在VJ上交才知道过了。 当然可能是我太菜了。 【题目】 Topcoder 给定nnn个权值,要么非负,要么为−1-1−1,你现在可以用n−1n-1n−1条边连接这些权值得到一棵树。我们称一个权值是有用的当且仅当它它和至少一个非负权值相连且它本身不为负,这棵树的权值为所有有用的权值之和。 求有...

MEET YOU FIRST TIME 335

Ubuntu20.04系统笔记本网卡AX211无法找到wifi问题

之前电脑的系统是18.04基本上安装好了系统,可以直接连上wifi,在买了拯救者y9000p2022版本之后,因为网卡太新,安装ubuntu18.04或者20.04之后会没有wifi连接,非常不方便。于是上网找了各种帖子去解决这个问题。具体实现有所不同。 主要参考了这个帖子来解决的:http://t.csdn.cn/7807R 首先: sudo apt install flex bison 然后: git clone https://github.com/intel/backpor.

weixin_42825962的博客 1万+

基于价值的深度强化学习:DQN

本文主要是介绍DQN原理和算法伪代码和代码实现,算法实现包括pytorch版本和stable-baselines3版本

溯源的专栏 1083

[meet in middle 矩阵树定理 容斥原理] SRM 551 div1 SweetFruits

集训队论文传送门大概就是我们先用meet in middle求出有恰好k个真甜的方案数 然后我们求这些东西的生成树个数 乘在一起的和就是答案 我们让真甜连真甜 真甜连不甜 假甜连不甜 不甜连不甜 跑一发矩阵树定理 这样只能保证这些真甜的某个子集是真甜 那么我们需要用 0~k-1 的简单容斥一下// BEGIN CUT HERE #include<conio.h> #include<sstr

雯舞 754

一篇文章带你快速入门 MATLAB

文章目录一、认识 MATLAB 界面二、MATLAB 的运行方式三、Matlab 中的窗口1. 命令窗口2. MATLAB的程序编辑窗口3. 工作空间窗口4. 命令历史窗口5. 图形窗口6. 当前目录窗口四、MATLAB的帮助系统1. 帮助命令2. 联机帮助五、其他知识补充1. MATLAB的搜索路径2. 变量命名规则3. M文件命名规则 一、认识 MATLAB 界面 在 MATLAB Desktop 中,工具条取代了菜单和工具栏。应用程序库收纳了 MATLAB 产品系列的应用程序,单一文件应用程序打包为一

南淮北安的博客 5126

[TopCoder12141]SweetFruits

vjudge description 有\(n\)个水果,有一些水果是香的,它们各有一个香度值,剩下的水果是不香的。 现在你要把这\(n\)个水果连成一棵树,定义一个水果是真香的当且仅当它是香的且他与一个香的水果相邻。定义一棵树的香度为这棵树上真香的水果的香度值之和。 求满足香度不超过某个给定值的树的个数模\(10^9+7\)。 \(n\le40\) sol 设香的水果一共有\(m\)个...

abcyan1235的博客 367

华为OD机试2025A卷 - 用户调度问题(Java & Python& JS & C++ & C )

题目要求每个用户依次选择当前所能选择的最小资源消耗策略,并且若有多个策略的资源消耗相同,则选择最后一个策略。每个用户的选择是独立的,只考虑该用户的策略和相邻用户的约束,不考虑整个调度序列的全局资源消耗。每个用户根据自己的当前状态(即自己的三种选择的资源消耗)做出局部最优选择:在当前可选的策略中,选择消耗最小的那个。如果有多个最小值,则选择最后一个(根据题意)。这一选择是局部的最优,即在当下最有利的选择,但并不保证最终的整体系统资源消耗是最小的。

算法大师! 1万+

微信小程序 - 解决报错 {“errcode“:41002,“errmsg“:“appid missing, rid: X“} 微信报错错误码errcode“:41002问题分析及解决教程(详细排查)

【微信小程序】报错{“errcode“:41002,“errmsg“:“appid missing, rid: 64e55770-67c1fb7e-027c5a70“}:【微信小程序】微信小程序登录请求出现appid missing提示,微信公众号{"errcode":41002,"errmsg":"appid missing"},微信 报错{“errcode“:41002,“errmsg“:“appid missing,微信小程序获取openid返回appid missing的问题,微信小程序提示Erro

🏆 前端领域优质创作者 5654

[容斥原理][Meet-in-middle][Matrix-Tree定理] SRM551 Div1 Hard SweetFruits

SolutionSolutionSolution 将原问题分成两个子问题。 从所有甜的水果中选出kkk个水果作为真甜的,要求他们甜度之和不超过maxSweetnessmaxSweetnessmaxSweetness的方案数cntkcntkcnt_k 令nnn为甜的水果数目,求出组成的树的方案数treektreektree_k使得nnn个甜的水果中恰有kkk个水果为真甜的。 ans=∑k=0...

Vectorxj的博客 632

Codex入门01-环境安装(小白入门:手把手教你安装配置,国内网络也能搞定)

本文手把手教你从零搭建 Codex CLI 开发环境。内容涵盖 Node.js 安装(macOS/Windows/Linux)、Codex CLI 全局安装、ChatGPT 账号登录认证,以及国内网络代理配置。还包括常见问题排查和一键启动脚本编写。跟着截图一步步操作,10分钟搞定全部环境,开始用AI写代码!

yueyeguzhuo的专栏 344

冲刺NOI2017 (20) 苹果树 (矩阵树定理 容斥原理 Meet in middle)

题目大意给定nn个苹果,对于苹果ii,其甜度为cic_i,cic_i>=-1。假如cic_i=-1,代表苹果ii是坏的,否则它是好的。现在要用n−1n-1条线把这n个苹果连成一个联通块,也就是一棵树,定义树上一个苹果是有用的,当且仅当它是一个好苹果,且与至少一个好苹果直接相连。一棵树的权值定义为树上的有用的苹果的甜度之和。给定limitlimit,问有多少种不同的生成树,满足其权值小于等于limit

yashem66 1001

迈瑞BS系列全自动生化分析仪LIS协议接口手册(内含HL7和ASTM)

迈瑞BS系列全自动生化分析仪LIS协议接口手册,内含HL7和ASTM)

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

TC SRM 551 div2 题解

转载请注明出处,谢谢 http://blog.csdn.net/ACM_cxlove?viewmode=contents           by---cxlove 终于在TC过了两题,可惜第三题看错了题目。 250pt:只需要判断有几种颜色即可。 class ColorfulBricks{ public: int countLayouts(string bricks){ bool

窝不是爱酱,喵~~~~ 2361

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

SRM 551 Div1

noip d2t3 没清数组实力滚粗,赶紧做一波SRM 冷静一下。。。。250pts最终答案里至少有一个点没改变位置。因此枚举没改变位置的点,然后把两边和他同色的点移过来的花费排个序,从小到大往里加,直到超过最大花费,更新一下答案。#include <bits/stdc++.h> using namespace std; int n,top,cnt,sum,ans; int st[110]; cla

make_it_for_good的博客 503

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

【Topcoder SRM523】【meet in the middle】 AlphabetPaths 搜索

TC卡的不要不要的,现在翻不了墙,先不放题目,直接说一下大意:有一个R*C 的矩阵,矩阵里每个格子要么为空要么是一个0~20 的整数,求有多少条包含21 个格子的路径满足:路径上相邻两个格子有一条公共边,且0~20 每个数字在路径上恰好出现一次(R,C<21)然后这道题如果直接搜索是要T的,因为不知道起点,不知道终点,我们可以枚举中点,然后yong每一位1表示一个颜色,开一个2212^{21}的数组

anantheparty的博客 468

[容斥 状压DP 树形DP] BZOJ 4455 [Zjoi2016]小星星 & UOJ #185 【ZJOI2016】小星星

杜老师说的哦 UOJ上需要卡常 #include #include #include #include #define cl(x) memset(x,0,sizeof(x)) using namespace std; typedef long long ll; inline char nc(){ static char buf[100000],*p1=buf,*p

雯舞 690

jzoj5899 资源运输 矩阵树定理

Description Solution 这真的是noip难度吗(;′⌒`) 考试的时候漏掉这个大裸题了。我们知道矩阵树定理可以求出生成树的方案,变元矩阵树定理可以求出所有生成树边权乘积的和。这两个除一下就是答案了 Code #include &lt;stdio.h&gt; #include &lt;string.h&gt; #include &lt;algorithm&gt; #defi...

olahiuj的博客 345

【2019省选模拟】—树(并查集+容斥)

先不考虑修改 考虑直接不好求,改成求gcdgcdgcd不为1的个数 容斥一下就是一个质数时联通的点对个数-2个质数的积时联通的点的个数+3个质数积联通的点的个数…… 发现实际上就是μ\muμ 联通的点的个数实际上很好求,用并查集维护一下,mergemergemerge的时候加一个sizsizsiz的积就可以了 但每次不能直接重置,用一个指针维护一下回收被修改的sizsizsiz和fafafa,并查...

Stargazer的博客 229

[容斥 DP] Topcoder SRM 498 DIV1 Hard. FoxJumping

容斥 令 fi,jf_{i,j} 表示走了 ii 步不合法的,x和y都走了 jj 的方案数 li,jl_{i,j},ri,jr_{i,j} 分别表示在x,y方向上随便走了 ii 步,走了 jj 的方案数那么答案是 ∑d=0R(−1)d(Rd)∑i=0nfd,i×lR−d,n−i×rR−d,m−i \sum_{d=0}^R(-1)^d{R\choose d}\sum_{i=0}^nf_{d,i}

CE玩家 678

【jzoj5050】【颜色树】【容斥原理】【树形动态规划】

题目大意传说中,这棵不见边际的树有N个节点,每个节点都有1片叶子,每片叶子都拥有K种颜色中的一种,独孤玉溪喜欢爬到这棵树上,沿着一条路线摘叶子,并拥有所有颜色的叶子。独孤玉溪会选择一个起点,并沿着树边走,然后最终停在一个终点上(起点和终点可能相同),当然了每一个结点只能经过一次(每一片叶子只能摘一遍)。独孤玉溪突生奇想,有多少种不同的方案能满足自己呢?(两种方案不同当且仅当起点不同或终点不同)。解题

inklutcuah’s blog 566

Topcoder SRM 503 DIV1 500 KingdomXCitiesandVillages

KingdomXCitiesandVillagesTask:给定n个城市和m个村庄的坐标。要求将每一个村庄都连接到城市。 你每一次选定一个未连接的村庄,寻找这个村庄到其他一个已经连接到城市的村庄或者是一个城市的最短距离并连接,当然,如果有多个相等的最短距离,你选定其中的每一条道路的概率是均等的,求最后将村庄全部连接到城市的道路长度的期望值。(n,m<=50n,m<=50) Solution:

zqh_wz 451

topcoder SRM 517 div1 AdjacentSwaps 分析与题解

题目大意: 给定一个N个数的排列,要将其经过N-1次的交换(只能是相邻位置数的交换),变成0到N-1的排列,问有多少种交换的排列方式。 rng_58的题,费脑筋。 这个一个关于排列的inversion的题。排列的inversion代表排列的有序程度。排列的inversion的数量从0到n*(n-1)/2。 由此得出结论,要将一个排列经过N-1次的交换,变成0到N-1的排列,其inversi

xiaobaoo的博客 577

【BZOJ3534】重建(矩阵树定理)

题面 BZOJ 洛谷 题解 这。。。。 矩阵树定理神仙用法???? #include&lt;iostream&gt; #include&lt;cmath&gt; using namespace std; #define ll long long #define eps 1e-8 int n; double g[55][55],s=1; double Gauss() { ...

小蒟蒻yyb的博客 266

srm 551

资瓷点此阅读QvQ250Description题意:一个长度最多5050的字符串,每次操作可以交换相邻的两个字符,问,经过最多MaxSwapsMaxSwaps次交换之后,最多能让多少个相同的字符连起来Solution枚举一个字符,让其他字符往这里即可,取最小即可Code#include <bits/stdc++.h> using namespace std; #define pb push_back

mlzmlz95的专栏 471
上一篇: [矩乘优化DP] Topcoder SRM550 DIV1 Hard. ConversionMachine
下一篇: [容斥 & 状压DP & FFT] Tco 2016 Final. HamiltonianPaths
LowestJN
博客等级 码龄10年 76粉丝 422原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值