H Hip To Be Square Day5——NWERC2012
这个题目巨坑啊。调试的时间加起来绝对超过1天整。
不过终于调试出来了,真心感动地尿流满面啊。
题目的意思是给你一个区间[A,B],可以从区间里选出任意多个整数,使得这些整数的积是一个不超过 2^126的 平方数。
比赛的时候的想法就基本和题解差不多了,但是依然没有能够A出来。神坑啊。
知道现在才搞定。
首先我们可以知道这个区间的右端点不超过4900,在1-4900里面有70个平方数。所以只要给定的区间包含了一个或多个平方数,我们直接输出最小的那个平方数就可以了哦。这样我们可以保证区间的长度小于139。
但是我们仍然无法圆满地解决这个问题,因为2^138依然是一个巨大的数字,时间和空间都是无法承受的。
再想优化的办法。我们可以发现,有的数字是一定不能选的,那就是区间里仅被含有一次的素数因子,因为只要你选了这个数,无论你接下来怎么选择,都无法凑成一个平方数。(但是值得注意的是,如果区间的一个数含有独特的因子,但是其含有的是该素数因子的平凡的话,也不能被筛去,我就是这里Wa出翔了)
这样我们可以发现我们可以把可选的数字的个数降低到不超过50。
接下来还有最后一个优化,题目里面说过最后的那个平方根不会超过2^63,这样等于是那个平凡数不会超过2^126,这样我们应该选择的数的个数就只有12个左右了。
(可以这样理解,前面的平方数之间的距离比较窄,所以个数不会多;后面的平方数之间距离虽然比较宽,但是本身比较大,所以也不会选择太多,这样考虑就知道了所有的个数不超过12个咯)。
有了这个我们就可以逐步枚举所有的组合情况了,(注意从个数少的枚举到个数多的,同时注意数小的数要先进行判定,这样保证找到的第一个可行解是最小解——这里题解写的是要用单调队列优化,但是我是这样做的,先保存所有选择一个的情况,然后判断并且由此推出所有选择两个的情况 ,每次对于当前因子数的所有数都处理完成后,对下面一列进行一次排序就好了——单调队列不会写T_T 。这样就保证了第一次找到的解是最小解了。)
其实在实现的过程中有好多的小细节,比如位运算的时候,1要写成(ll)1,不然就等着爆吧。还有对于两种组合后积大小的比较我是依靠一个double来比较的,个人认为这个方法略怂,但是还挺管用,嘿嘿。
详细的就见代码吧!
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#define ll unsigned long long
#define maxQ 1000000//理论上来说要开的大一些
#define maxn 4920
using namespace std; struct node{
double tot;
ll id;
}cur,p; vector<int> vet[maxn+]; int prim[maxn+],f1[maxn+],Pnum,num[];
int N[],t[],s[],A,B,tim,ans[],pos,cas=;
bool b[maxn+],flag[maxn+];
node Q[][maxQ];
ll total; bool cmp(node n1,node n2)
{
return n1.tot<n2.tot;
} void getprim()
{
for (int i=; i<maxn; i++)
{
if (b[i]) continue;
prim[++Pnum]=i,f1[i]=Pnum;
for (int j=i+i; j<maxn; j+=i) b[j]=true;
}
for (int i=; i<; i++)
{
int k=i;
for (int j=; prim[j]<=k; j++)
while (k%prim[j]==) vet[i].push_back(prim[j]),k/=prim[j];
}
} void select_use_element()
{
int beg;
for (int i=; i<=Pnum; i++)
{
//if (prim[i]<50) continue;
//if (A%prim[i]==0) tim=1; else tim=0;
if (A%prim[i]==) beg=A;
else beg=(A-A%prim[i])+prim[i];
if (B>=beg) tim=(B-beg)/prim[i]+;
else tim=;
if (tim>) continue;
//if (prim[i]<50) continue;
for (int j=prim[i]; j<maxn; j+=prim[i]) flag[j]=true;
//if (prim[i]<=65) continue;
for (int j=prim[i]*prim[i]; j<maxn; j+=prim[i]*prim[i]) flag[j]=false;
}
tim=;
for (int i=A; i<=B; i++) if (!flag[i]) num[++tim]=i;//,cout<<i<<' ';//tim最终表示有多少个有用的数。
//cout<<" tim : "<<++cas<<' '<<tim<<" "<<A<<' '<<B<<endl;
} void output_digit(ll x)
{
while (x) cout<<(x&),x>>=; cout<<endl;
} bool check(int x,int y)
{
p=Q[x][y];
memset(ans,,sizeof ans);
for (int i=; i<=tim; i++)
if ((p.id)&((ll)<<(i-)))
{
for (unsigned k=; k<vet[num[i]].size(); k++)
ans[f1[vet[num[i]][k]]]++;
}
//for (int i=1; i<45; i++) cout<<ans[i]<<' '; cout<<endl;
for (int i=; i<; i++)
{
if (ans[i]%!=)
{
ans[]=-;
return false;
}
}
//output_digit(p.id);
ans[]=;
return true;
} void queue_operation()
{
N[]=; s[]=,t[]=;
p.id=,p.tot=;
for (int i=; i<=tim; i++)
{
cur.tot=num[i],cur.id=((ll)<<(i-));
Q[][++t[]]=cur;
}
sort(Q[]+,Q[]++t[],cmp);
int now=,next;
while (N[now]<=)
{
//cout<<"Nnow: "<<N[now]<<' '<<t[now]<<endl;
next=-now;
s[next]=,t[next]=,N[next]=N[now]+;
for (int i=s[now]; i<=t[now]; i++)
{
if (check(now,i)) return;
cur=Q[now][i];
for (pos=; ((ll)<<(pos-))<=cur.id; pos++) ;
//output_digit(cur.id);
for (int j=pos; j<=tim; j++)
if (((cur.id)&((ll)<<(j-)))==)
{
t[next]++;//=(t[next]+1)%maxQ;
p.tot=cur.tot*num[j];
p.id=(cur.id)|((ll)<<(j-));
Q[next][t[next]]=p;
}
}
sort(Q[next]+,Q[next]++t[next],cmp);
swap(now,next);
}
} void output_ans()
{
if (ans[]==-) { cout<<"none\n"; return; }
total=;
for (int i=; i<; i++)
for (int j=; j+j<=ans[i]; j++) total*=prim[i];
cout<<total<<endl;
} int main()
{
//freopen("C:/Users/Administrator/Desktop/data.in","r",stdin);
//freopen("C:/Users/Administrator/Desktop/data.out","w",stdout);
getprim();
while (cin>>A>>B)
{
memset(ans,,sizeof ans);
ans[]=-;
for (tim=; tim*tim<=B; tim++) if (tim*tim>=A) break;
if (tim*tim<=B)
{
cout<<tim<<endl;
continue;
}
memset(flag,false,sizeof flag);
select_use_element();
queue_operation();
output_ans();
}
return ;
}
H Hip To Be Square Day5——NWERC2012的更多相关文章
- 2012-2013 Northwestern European Regional Contest (NWERC 2012)
B - Beer Pressure \(dp(t, p_1, p_2, p_3, p_4)\)表示总人数为\(t\),\(p_i\)对应酒吧投票人数的概率. 使用滚动数组优化掉一维空间. 总的时间复杂 ...
- FFmpeg的H.264解码器源代码简单分析:宏块解码(Decode)部分-帧间宏块(Inter)
===================================================== H.264源代码分析文章列表: [编码 - x264] x264源代码简单分析:概述 x26 ...
- GNU C 扩展(转)
GNU CC 是一个功能非常强大的跨平台 C 编译器,它对 C 语言提供了很多扩展,这些扩展对优化.目标代码布局.更安全的检查等方面提供了很强的支持.这里对支持支持 GNU 扩展的 C 语言成为 GN ...
- Java 中的泛型详解-Java编程思想
Java中的泛型参考了C++的模板,Java的界限是Java泛型的局限. 2.简单泛型 促成泛型出现最引人注目的一个原因就是为了创造容器类. 首先看一个只能持有单个对象的类,这个类可以明确指定其持有的 ...
- Berserk Rook
Berserk Rook As you may know, chess is an ancient game for which almost everyone has at least a basi ...
- Postman接口自动化测试实例用到的完整的SM2前端加密算法代码
var __g__ = {}; !function(t,e){"object"==typeof exports?module.exports=exports=e():"f ...
- 调试器GDB的基本使用方法
GDB调试的三种方式: 1. 目标板直接使用GDB进行调试. 2. 目标板使用gdbserver,主机使用xxx-linux-gdb作为客户端. 3. 目标板使用ulimit -c unlimited ...
- Python--Click
Click Click 是 Flask 的开发团队 Pallets 的另一款开源项目,它是用于快速创建命令行的第三方模块. 我们知道,Python 内置了一个 Argparse 的标准库用于创建命令行 ...
- C#学习之委托和事件
C#学习中,关于委托和事件的一些见解: 一.C语言中的函数指针 想要理解什么是委托,就要先理解函数指针的概念.所谓函数指针,就是指向函数的指针(等于没说-.-).比如我定义了两个函数square和cu ...
随机推荐
- 20155235 2016-2017-2《Java程序设计》课程总结
每周作业链接汇总 预备作业一:学期前作业 预备作业二:技能获取与C语言学习情况 预备作业三:安装虚拟机与Linux的学习 第一周作业:20155235 2006-2007-2 <Java程序设计 ...
- PyQt5 结合 matplotlib 时,如何显示其 NavigationToolbar
本文目的:展示 PyQt5 结合 matplotlib 时,如何显示其 NavigationToolbar. 本人搜遍所有网络无果,没办法,查看PyQt5源代码,最终才搞明白...特此留记. 〇.Py ...
- Why HBase
3.1.1,为什么选用HBases a) 容量巨大 HBase 的单表可以有百亿行.百万列,数据矩阵横向和纵向两个维度所支持的数据量级 都非常具有弹性.传统的关系型数据库,如 Oracle ...
- 手撕一个 Galgame 神器——Shub-Niggurath Project
一.想法 Galgame 我们大概可以分为好用的 Galgame 和好玩的 Galgame,但是如果你把好玩的 Galgame 拿来用的话,有时候会十分让人着急.如果你躺在床上,一只手还在按压键盘实际 ...
- Android线程管理(一)——线程通信
线程通信.ActivityThread及Thread类是理解Android线程管理的关键. 线程,作为CPU调度资源的基本单位,在Android等针对嵌入式设备的操作系统中,有着非常重要和基础的作用. ...
- 【C#利用后台动态加载数据】Winform“防界面卡死”【BackgroundWorker】类
using System.ComponentModel 直接使用EgProgressBar方法 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 2 ...
- C++操作符优先级带来的错误
在刷LeetCode题目:190. 颠倒二进制位:颠倒给定的 32 位无符号整数的二进制位时,可以利用左移和右移操作符来实现数字翻转: 错误解法: class Solution { public: u ...
- Selenium2+python自动化-xpath定位语法
前言 在上一篇简单的介绍了用工具查看目标元素的xpath地址,工具查看比较死板,不够灵活,有时候直接复制粘贴会定位不到.这个时候就需要自己手动的去写xpath了,这一篇详细讲解xpath的一些语 ...
- Java解惑之TreeSet是如何去重的
引言: 最近在处理一个问题,大致是这个样子,从数据库里面取出一个集合,取出来的数据放到一个JavaBean里面.结果得到的集合长度为1. TreeSetSet的一个实现,默认实现排序:故TreeSet ...
- YAML 基础
YAML 基础 简介 对象 数组 常量 引用 1. 简介 YAML 是专门用来写配置文件的语言,非常简洁和强大! 它的基本语法规则有: 大小写敏感: 使用缩进表示层级关系: 缩进时不允许使用 Tab ...