1307E - Cow and Treats

题意

有一排给定口味的草,并且给m头牛,每个牛都只吃一种口味的草,并且要吃给定数量个。现在可以安排牛从两边出发,方向向另一方向进发,每次路过符合他口味的草就会吃,吃到他需要的数量就会停下开始睡觉,开始睡觉后就是个路障,不能通行。如果一个牛吃到了他需要的数量的草就会Happy,让你安排牛从两边走,求最大数量的happy牛的数量,并且求出满足最大数量情况下的方案数。方案的不同体现在集合的不同,比如从左边出发的牛集合不同,就算做不同方案。

题解

首先我们先来解决最大数量的问题。对于吃每一种口味的牛来说,同口味的牛,不能从同方向出发超过两只,显然可得,那么也就是说同一个口味的牛最多左边右边出发一只,也就是最多2只。对每一种牛求一下即可得最大口味数,本题的难点在于求方案数。这里要分左右n只有5000,一个很自然的想法是枚举从左和从右的分界线。假如从左开始到分界线一共有right[i]个i口味的草,那么需要吃的数量小于等于right[i]的牛都可以从这里出发,左边同理。我们设从左出发满足条件的牛有a个,从右有b个,那么从两边方案数量为a*b-min(a,b) 这里用的是容斥的思想。因为min(a,b),一定是max(a,b)的子集,所以可得。A交B的数量为min(a,b),从一边的方案数为(a+b)。从左到右枚举分界点算一遍即可。这里还要解决的是重复的问题,例如[1,10]区间假如[1,4] [7,10] 分别是两边行进的路径,那么[1,5][5,10] 就会把这个集合再算一遍,就重复了。怎么解决这个问题呢,我们可以考虑枚举每一个有牛休息的点,对于这个点,固定该点口味的牛,其他的点只要符合要求随意停留,这样就能不重不漏计算出方案数了。

这里可以用upper_bound 很方便得找到符合条件的数量,同时用std::binary_search可以方便判断一个数在不在数组中。

代码

#include<bits/stdc++.h>
#define pb push_back
#define mkp make_pair
using namespace std;
typedef long long ll;
const int mod=1e9+7;
const int maxn=5000+5;
int lefts[maxn],rights[maxn],num[maxn],ways[maxn],s[maxn];
int n,m;
vector<int>v[maxn];
void solve1(int id){
int a=upper_bound(v[id].begin(),v[id].end(),rights[id])-v[id].begin();
int b=upper_bound(v[id].begin(),v[id].end(),lefts[id])-v[id].begin();
ll cnt2=a*b-min(a,b);//tow sides
ll cnt1=a+b;//one sides
if(cnt2>0){
ways[id]=cnt2;
num[id]=2;
}
else if(cnt1>0){
ways[id]=cnt1;
num[id]=1;
}
else {
ways[id]=1;
num[id]=0;
}
}
ll ans_tot=-1,ans_ways=1;
ll add(ll a,ll b ){
a=(a+mod)%mod,b=(b+mod)%mod;
return (a+b+mod)%mod;
}
void update(ll tmp_tot,ll tmp_ways){
if(tmp_tot>ans_tot){
ans_tot=tmp_tot;
ans_ways=tmp_ways;
}
else if(tmp_tot==ans_tot){
ans_ways=add(ans_ways,tmp_ways);
}
}
void solve2(int id){
int a=upper_bound(v[id].begin(),v[id].end(),rights[id])-v[id].begin();
if(rights[id]>=lefts[id])//因为同一种口味同1数量的牛不可能有2个 所以固定一个在边界睡觉后 如果right[id]>=left[id] 既这个牛也满足从左边出发,只需要减掉他即可
a--;
if(a>0){
ways[id]=a;
num[id]=2;
}
else {
ways[id]=1;
num[id]=1;
}
}
ll mul(ll a,ll b){
a=(a+mod)%mod;
b=(b+mod)%mod;
return (a%mod)*(b%mod)%mod;
}
ll fpow(ll a,ll b){
ll ans=1;
while(b){
if(b&1)ans=mul(ans,a);
a=mul(a,a);
b>>=1;
}
return ans;
}
ll inv(ll x){
return fpow(x,mod-2);
}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)scanf("%d",&s[i]),rights[s[i]]++;
for(int i=1;i<=m;i++){
int x,y;
scanf("%d%d",&x,&y);
v[x].push_back(y);
}
for(int i=1;i<=m;i++)sort(v[i].begin(),v[i].end());
for(int i=1;i<=n;i++){
solve1(i);
}
ll tmp_tot=0,tmp_ways=1;
for(int i=1;i<=n;i++){
tmp_tot+=num[i];
tmp_ways=mul(tmp_ways,ways[i]);
}
update(tmp_tot,tmp_ways);
//cout<<ans_tot<<" "<<ans_ways<<endl;
for(int i=1;i<=n;i++){
tmp_tot-=num[s[i]];
tmp_ways=mul(tmp_ways,inv(ways[s[i]]));
//cout<<"??? "<<tmp_ways<<endl;
rights[s[i]]--,lefts[s[i]]++;
if(binary_search(v[s[i]].begin(),v[s[i]].end(),lefts[s[i]])){
solve2(s[i]);
update(tmp_tot+num[s[i]],mul(tmp_ways,ways[s[i]])); //cout<<i<<" "<<lefts[s[i]]<<" "<<tmp_tot+num[s[i]]<<" "<<ways[s[i]]<<endl;
//cout<<ans_tot<<" zzz "<<ans_ways<<endl;
}
solve1(s[i]);
tmp_tot+=num[s[i]];
//cout<<ways[s[i]]<<endl;
tmp_ways=mul(tmp_ways,ways[s[i]]);
}
printf("%lld %lld\n",ans_tot,ans_ways);
return 0;
}

1307E - Cow and Treats 二分 枚举边界 容斥的更多相关文章

  1. hdu-2197 本原串---枚举因子+容斥定理

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=2197 题目大意: 由0和1组成的串中,不能表示为由几个相同的较小的串连接成的串,称为本原串,有多少个 ...

  2. 牛客练习赛43 Tachibana Kanade Loves Game (简单容斥)

    链接:https://ac.nowcoder.com/acm/contest/548/F来源:牛客网 题目描述 立华奏是一个天天打比赛的萌新. 省选将至,萌新立华奏深知自己没有希望进入省队,因此开始颓 ...

  3. POJ 3189——Steady Cow Assignment——————【多重匹配、二分枚举区间长度】

     Steady Cow Assignment Time Limit:1000MS     Memory Limit:65536KB     64bit IO Format:%I64d & %I ...

  4. YYHS-分数(二分+容斥)

    题目描述 KJDH是个十分善于探索的孩子,有一天他把分子分母小于等于n的最简分数列在了纸上,他想找到这些分数里第k小的数,这对于KJDH来说当然是非常轻易,但是KJDH最近多了很多妹子,他还要去找妹子 ...

  5. 第k个互质数(二分 + 容斥)

    描述两个数的a,b的gcd为1,即a,b互质,现在给你一个数m,你知道与它互质的第k个数是多少吗?与m互质的数按照升序排列. 输入 输入m ,k (1<=m<=1000000;1<= ...

  6. Codeforces 801C Voltage Keepsake(二分枚举+浮点(模板))

    题目链接:http://codeforces.com/contest/801/problem/C 题目大意:给你一些电器以及他们的功率,还有一个功率一定的充电器可以给这些电器中的任意一个充电,并且不计 ...

  7. nyoj762——分解质因数+容斥+二分

    第k个互质数 时间限制:1000 ms  |  内存限制:65535 KB 难度:4   描述 两个数的a,b的gcd为1,即a,b互质,现在给你一个数m,你知道与它互质的第k个数是多少吗?与m互质的 ...

  8. 【周期性/容斥+二分】POJ2773-HAPPY 2006

    [题目大意] 求与n互质的第k个数. [思路] 先求出小于k且与n互质的数,再利用gcd(bt+a,b)=gcd(a,b)的性质求解,效率低.枚举与n互质的数的效率是O(nlogn),求解第k个数的效 ...

  9. POJ 2112—— Optimal Milking——————【多重匹配、二分枚举答案、floyd预处理】

    Optimal Milking Time Limit:2000MS     Memory Limit:30000KB     64bit IO Format:%I64d & %I64u Sub ...

随机推荐

  1. 05.JS函数

    前言: 学习一门编程语言的基本步骤(01)了解背景知识(02)搭建开发环境(03)语法规范(04)常量和变量(05)数据类型(06)数据类型转换(07)运算符(08)逻辑结构(09)函数9.函数——f ...

  2. 怎样将应用程序快捷方式添加到win10开始菜单栏中去

    怎样将应用程序快捷方式添加到win10开始菜单栏中去 找到需要固定的应用程序的安装文件的位置,右键,在弹出的菜单中选择“固定到开始屏幕”即可. 或者是找到需要固定到开始菜单的应用程序的快捷方式,右键, ...

  3. 什么是kafka,怎么使用? (3)

    上次我因为在windows上解压一个.gz的包没有解压出来,故需要在linux使用kafka,而且这kafka的快速开始上有个zookeeper的文件配置 所以我感觉有必要把dubbo-zookeep ...

  4. LeetCode 面试题 02.01. 移除重复节点

    编写代码,移除未排序链表中的重复节点.保留最开始出现的节点. 示例1: 输入:[1, 2, 3, 3, 2, 1] 输出:[1, 2, 3]示例2: 输入:[1, 1, 1, 1, 2] 输出:[1, ...

  5. 在腾讯云上配置.NetCoreWeb

    1.购买服务器 2.远程登录(账号密码在上图铃铛里的消息里) 3.安装iis 3.安装.NetCore相关 下载最新版本.NET Core Windows Server Hosting https:/ ...

  6. python3的bytes数据类型

    python已升级到了3.0,都说现在是属于python3,未来也是属于python3,那python3到底改了些什么呢? 其中我记得非常清楚的是,python3对文本和二进制数据作了更为清晰的区分. ...

  7. 剑指offer-拓展训练-N皇后的问题-全排列

    /* 题目: N皇后的问题. */ /* 思路: 全排列. 声明一个具有N个元素的数组curr,每个下标i(0>i>n)代表行,每个curr[i]代表列,所以初始化为curr[i] = i ...

  8. beego的请求数据处理

    我们经常需要获取用户传递的数据,包括 Get.POST 等方式的请求,beego 里面会自动解析这些数据,你可以通过如下方式获取数据: GetString(key string) string Get ...

  9. MySQL 8 服务器插件

    安装插件 内置插件时服务器能够自动识别的,通常在服务器启动时加载内置插件. 在mysql.plugin表中注册的插件,这种插件不同于内置插件(内置插件不需要注册),通常在服务器启动时会加载mysql. ...

  10. 关于Spring注入参数到static静态参数失败问题处理。解决Autowired annotation is not supported on static fields的问题

    直接贴代码 把注入参数的注解加到set方法上面去即可. 因为这是一个工具类用到的config,所以一开始没有加@Component,还是依然为空,加上之后就正常能注入了