uoj#750-[UNR #6]小火车【二分,折半,鸽笼原理】
正题
题目链接:https://uoj.ac/problem/750
题目大意
给出\(n\)个数字和一个\(p\),保证\(2^n> p\)。现在要求一个序列\(w\)满足\(w_i\in[-1,1]\),使得\(\sum_{i=1}^nw_ia_i\equiv 0\pmod p\)
\(1\leq p<2^n,1\leq n\leq 40,0\leq a_i<p\)
解题思路
我们考虑从数字集合\(S\)中找两个数字和相同的集合\(T_1,T_2\),那么\(T_1-T_1\cap T_2\)和\(T_2-T_1\cap T_2\)的和也相等,此时我们一边选\(1\)一边选\(-1\)即可,如果有一边是空的也行,这样另一边直接合法。
然后在\(S\)中选出集合的方案有\(2^{n}\)种,然后因为\([0,p)\)有不超过这么多个数,所以肯定有重复的一个位置,所以肯定有解。
然后考虑怎么求这个解,看到这个范围我们考虑一下折半,我们搜出左右两边数字和的集合\(S_l,S_r\)。
如果左边或者右边有重复的就直接结束先,这样我们就能保证左右没有重复了,此时我们需要找到\(a,b\in S_l,c,d\in S_r\),使得\(a+c=b+d\),因为两个集合的都很大,这个看起来很不可做。
但是我们知道一定有解,这个条件肯定是有用的,我们考虑二分一下这个和。每次分割成左右两个区间\([l,mid],[mid+1,r]\),我们求出有多少对\(x\in S_l,y\in S_r\)满足\(x+y\in[l,mid]\),如果超过\(mid-l+1\)那么答案肯定在左区间,否则在右区间。
时间复杂度:\(O(2^{\frac{n}{2}}n)\)
code
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<map>
#define ll long long
using namespace std;
const ll N=45,M=1<<20;
ll n,p,L1,L2,a[N];
map<ll,ll> mp;pair<ll,ll> f[M],g[M];
bool check(ll l,ll r){
int L=0,R=0;ll ans=0;
for(int i=L1-1;i>=0;i--){
while(R<L2&&f[i].first+g[R].first<=r)R++;
while(L<L2&&f[i].first+g[L].first<l)L++;
ans+=R-L;
}
L=0;R=0;
for(int i=L1-1;i>=0;i--){
while(R<L2&&f[i].first+g[R].first-p<=r)R++;
while(L<L2&&f[i].first+g[L].first-p<l)L++;
ans+=R-L;
}
return ans>(r-l+1);
}
void solve(ll ansL,ll ansR){
ll k=ansL&ansR;ansL-=k;ansR-=k;
for(int i=0;i<n;i++){
if((ansL>>i)&1)printf("1 ");
else if((ansR>>i)&1)printf("-1 ");
else printf("0 ");
}
return;
}
signed main()
{
scanf("%lld%lld",&n,&p);
for(ll i=0;i<n;i++)scanf("%lld",&a[i]);
L1=(1<<n/2);
for(int s=1;s<L1;s++){
for(int i=0;i<n/2;i++)
if((s>>i)&1)(f[s].first+=a[i])%=p;
f[s].second=s;
}
L2=(1<<n-n/2);
for(int s=1;s<L2;s++){
for(int i=0;i<(n-n/2);i++)
if((s>>i)&1)(g[s].first+=a[i+n/2])%=p;
g[s].second=s;
}
sort(f+1,f+L1);sort(g+1,g+L2);
for(int i=1;i<L1-1;i++)if(f[i].first==f[i+1].first){solve(f[i].second,f[i+1].second);return 0;}
for(int i=1;i<L2-1;i++)if(g[i].first==g[i+1].first){solve(g[i].second<<(n/2),g[i+1].second<<(n/2));return 0;}
ll l=0,r=p-1;
while(l<r){
ll mid=(l+r)>>1;
if(check(l,mid))r=mid;
else l=mid+1;
}
ll z=0,ansL=0,flag=0;
for(int i=L1-1;i>=0;i--){
while(z<L2&&f[i].first+g[z].first<r)z++;
if(f[i].first+g[z].first==r){
if(!flag)ansL=f[i].second+(g[z].second<<n/2),flag=1;
else{solve(ansL,f[i].second+(g[z].second<<n/2));return 0;}
}
}
z=0;
for(int i=L1-1;i>=0;i--){
while(z<L2&&f[i].first+g[z].first-p<r)z++;
if(f[i].first+g[z].first-p==r){
if(!flag)ansL=f[i].second+(g[z].second<<n/2),flag=1;
else{solve(ansL,f[i].second+(g[z].second<<n/2));return 0;}
}
}
// for(ll i=0;i<L2;i++)mp[g[i]]=i+1;
// for(ll i=0;i<L1;i++){
// ll x=(l+p-f[i])%p;
// if(mp[x]){
// mp[x]--;
// if(!mp[x]&&!i)continue;
// }
// }
return 0;
}
原文地址:https://www.cnblogs.com/QuantAsk/p/16573708.html
- Linux数据流重定向
- C++中消息自动派发之四 使用IDL构建Chat Server
- Linux Shell(二)——Shell的环境配置
- 支持插件的消息中间件【msg broker with plugin】
- Linux Shell(一)——Shell变量
- 智能指针shared_ptr【无锁设计基于GCC】
- 浅谈代码覆盖
- Base PyQt4, Simple Web APP Framwork
- Linux用户身份切换
- TCPDUMP 抓包
- Embeding Python & Extending Python with FFPython
- kNN最邻近规则分类
- 通用排行榜组件
- Future Pattern
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- Python—requests模块详解
- python爬虫伪装请求头---fake-useragent
- Flutter基础widgets教程-RaisedButton篇
- 记一次 excel vba 参考手册爬虫实战,不必要的一次爬虫。
- xray子域名扫描结果导出
- AWS的湖仓一体使用哪种数据湖格式进行衔接?
- python 行政区域地址标准化:业务经理填报的地址乱起八糟,高德接口有点厉害!
- python 行政区域地址标准化:业务经理填报的地址乱起八糟,高德接口有点厉害! -- 后续,使用分词思路完成解析
- pandas 一维台账数据与二维表格数据的转换
- Flutter基础widgets教程-Row篇
- padans 关于数据处理的杂谈 -- 时序数
- python pandas DataFrame 关于重复索引取值的一些坑
- selenium webdriver 如何添加cookie
- Flutter基础widgets教程-Scaffold篇
- python selenium 微信公众号历史文章随手一点就返回首页?郁闷之下只好将他们都下载下来。