A1339. JZPLCM(顾昱洲)
时间限制:3.0s   内存限制:256.0MB  
试题来源
  2012中国国家集训队命题答辩
问题描述
  给定一长度为n的正整数序列a,有q次询问,每次询问一段区间内所有数的lcm(即最小公倍数)。由于答案可能很大,输出答案模1000000007。
输入格式
  第一行,两个整数,n, q,分别表示数列长度和询问个数。
  下面n行,每行一个整数,第i行的整数为ai
  下面q行,每行两个整数l, r,表示询问下标i在[l, r]范围内的ai的lcm。
输出格式
  q行。对于每个询问,输出一行,表示对应的答案。
样例输入
3 3
123
234
345
1 2
2 3
1 3
样例输出
9594
26910
1103310  
数据范围
n,q<10w,ai<=1e9。
 
这题这么神我肯定要放上来啊。
首先51Nod的数据是经过弱化的,并没有那么强。
对于51Nod的数据,我们可以用一种比较皮的方法艹过去。
一些数的LCM就是对每个质数的指数取max。
对于大于sqrt(x)的质数,这个指数最大是1。所以对于这些数,我们只需要判断在这些区间内是否出现过就可以了。这个问题可以用莫队算法+桶实现。
对于小于等于sqrt(x)的质数,经过打表发现这种质数只会有约50个。我们可以把每一个数S[i]分解质因数后存进50个表里,每次询问对这50个质数分别来一次区间求最值。因为表定型后不涉及修改操作,可以使用ST表把单次询问降低到O(1)。
所以说这道题需要写两个程序。
莫队算法转移的复杂度是O(1)的,该部分复杂度是O(n*sqrt(n))。
倍增算法预处理的复杂度是O(50*n*log(n))的,处理询问复杂度是O(50*n)的。
鉴于这题空间不是很足,要对每个小质数一个一个处理ST表,空间复杂度为O(n*log(n)+n*50)。
 
但是对于Ai<=1e9就无能为力了。
然后队爷给了一种很强力的做法,发现我的思维能力跟队爷完全不在一个时代上。
一般我做题,先把问题模型化,一般化,再根据数据范围选择合适的算法/数据结构一顿爆艹。
但是队爷做题有两种思路,这就比我不知高到哪里去了。
一种思路:原问题 - 一般化(强化)的问题 - 解决一般化的问题 - 解决原问题。
另一种思路是:先思考某种特殊情况,一般是比较好处理的,再推广到原问题。
其实这种思路在很多解题报告中也有出现:
“我们讨论只有一条链的情况。”
“我们先来看一下没有约束的情况。”
“这个a很讨厌,我们先不管它。”
……
划下重点。
所以我们先来假设每一个数都是无平方因子数。
这种情况我只会莫队,果然是数据结构学傻(不对数据结构也不会写)。
这时候问题化为:某区间所有出现过的数的积(不同数的积)。
这是一个我不会的经典问题,好像之前看到有些题考这个?
 
对于上面的问题,我们考虑对于一组询问[l,r]。
找到每个数上一次出现的位置pre[i](如果没有出现就是0)。
那么就要求的是
对于这种问题,可以有如下解决方式:
设询问为f(l,r,l),则询问等价为

所以你要写一种数据结构,支持上面的操作。
显然可以离线+树状数组。
 
那么有平方甚至多次方因子呢?
假设一个数A[i]可以写成p的q次方(p为质数,q为满足被整除的最大值)。
那可以把这个数拆成q个数p,p^2,p^3……p^q,每个数的权值都是p。
于是问题就转化成了上面的弱化问题,只是区间长度变了而已。
于是这题就解决了(好神啊突然开车)。
 
略显尴尬的是我的代码比较长……
下面放对于51Nod数据的爆艹法。

#include    <iostream>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <vector>
#include <cstring>
#include <queue>
#include <complex>
#include <stack>
#define LL long long int
#define dob double
#define FILE "JZPLCM"
using namespace std; const int N = ;
const int Mod = 1e9+;
struct Node{int to,next;}E[N];
int n,m,P[N],vis[N],tot,S[N],Ny[N],block,A[][N],bel[N],bin[N],B[][N];
int Log[N],Pw[][N],Ans[N],res=,head[N],Tot;
struct Data{
int l,r,id;
bool operator <(const Data &d)const{
if(bel[l]==bel[d.l])return r<d.r;
return bel[l]<bel[d.l];
}
}Ask[N]; inline int gi(){
int x=,res=;char ch=getchar();
while(ch>''||ch<''){if(ch=='-')res*=-;ch=getchar();}
while(ch<=''&&ch>='')x=x*+ch-,ch=getchar();
return x*res;
} inline void link(int u,int v){
E[++tot]=(Node){v,head[u]};
head[u]=tot;
} inline void prepare(){
for(int i=;i<N;++i){
if(!vis[i])P[++tot]=i;
for(int j=;j<=tot;++j){
int ytk=i*P[j];if(ytk>=N)break;
vis[ytk]=;if(i%P[j]==)break;
}
}
Ny[]=;
for(int i=;i<N;++i)
Ny[i]=1ll*(Mod-Mod/i)*Ny[Mod%i]%Mod;
} inline void Insert(int x){
for(int e=head[x];e;e=E[e].next){
int y=E[e].to;bin[y]++;
if(bin[y]==)res=1ll*res*y%Mod;
}
} inline void Delete(int x){
for(int e=head[x];e;e=E[e].next){
int y=E[e].to;bin[y]--;
if(bin[y]==)res=1ll*res*Ny[y]%Mod;
}
} inline void Modui(){
memset(bin,,sizeof(bin));
Insert(S[]);int l=,r=;
for(int i=;i<=m;++i){
if(r<Ask[i].r)
for(int j=r+;j<=Ask[i].r;++j)
Insert(S[j]);
if(r>Ask[i].r)
for(int j=r;j>Ask[i].r;--j)
Delete(S[j]);
if(l<Ask[i].l)
for(int j=l;j<Ask[i].l;++j)
Delete(S[j]);
if(l>Ask[i].l)
for(int j=l-;j>=Ask[i].l;--j)
Insert(S[j]);
l=Ask[i].l;r=Ask[i].r;
Ans[Ask[i].id]=1ll*Ans[Ask[i].id]*res%Mod;
}
} int main()
{
freopen(FILE".in","r",stdin);
freopen(FILE".out","w",stdout); prepare();n=gi();m=gi();block=sqrt(n);
bin[]=;for(int i=;i<=;++i)bin[i]=bin[i-]*;
for(int i=,j=;i<=n;i*=,j++)Log[i]=j;
for(int i=;i<=N;++i)
if(!Log[i])Log[i]=Log[i-];
for(int i=;i<=n;++i)S[i]=gi(),bel[i]=i/block+;
for(int j=;j<=n;++j){
int ytk=S[j];
for(int i=;i<=;++i){
int num=;
while(ytk%P[i]==)num++,ytk/=P[i];
B[i][j]=num;
if(ytk==)break;
}
if(ytk>)link(S[j],ytk);
}
for(int i=;i<=;++i){
Pw[i][]=;
for(int j=;j<=;++j)
Pw[i][j]=1ll*Pw[i][j-]*P[i]%Mod;
}
for(int i=;i<=m;++i){
int l=gi(),r=gi();Ans[i]=;
Ask[i]=(Data){l,r,i};
}
for(int k=;k<=;++k){
for(int i=;i<=n;++i)A[][i]=B[k][i];
for(int i=;i<=;++i)
for(int j=;j<=n;++j)
A[i][j]=max(A[i-][j],A[i-][min(n,j+bin[i-])]);
for(int i=;i<=m;++i){
int l=Ask[i].l,r=Ask[i].r,dt=r-l+,Lg=Log[dt];
int Mx=max(A[Lg][l],A[Lg][r-bin[Lg]+]);
Ans[i]=1ll*Ans[i]*Pw[k][Mx]%Mod;
}
}
sort(Ask+,Ask+m+);Modui();
for(int i=;i<=m;++i)
printf("%d\n",Ans[i]);
return ;
}

莫队+倍增

然后是对于51Nod的数据很多地方跑不过原数据的树状数组。

#include    <iostream>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <vector>
#include <cstring>
#include <queue>
#include <complex>
#include <stack>
#define LL long long int
#define dob double
#define FILE "JZPLCM"
#define c233 printf("\n");
using namespace std; const int N = ;
const int M = N*;
const int Mod = 1e9+; struct Data{
int r,tr,kind,id;
bool operator <(const Data &d)const{
return tr<d.tr;
}
}opt[N*]; struct Pair{
int pre,id,val;
Pair(){};
Pair(int p,int i,int v){pre=p;id=i;val=v;}
bool operator <(const Pair &p)const{
return pre<p.pre;
}
}Y[M]; int n,m,P[N],tot,vis[N],A[N],cnt,ED[N],pre[M],bin[N],top,Ans[N],W[M],V[M];
struct BIT{
int T[M];
inline void clear(){
for(int i=;i<=cnt;++i)T[i]=;
}
inline int lb(int k){
return k&-k;
}
inline void update(int x,int val){
for(;x<=cnt;x+=lb(x))T[x]=1ll*T[x]*val%Mod;
}
inline int query(int x,int res=){
for(;x>;x-=lb(x))res=1ll*res*T[x]%Mod;
return res;
}
}T; inline int gi(){
int x=,res=;char ch=getchar();
while(ch>''||ch<''){if(ch=='-')res*=-;ch=getchar();}
while(ch<=''&&ch>='')x=x*+ch-,ch=getchar();
return x*res;
} inline void prepare(){
for(int i=;i<N;++i){
if(!vis[i])P[++tot]=i;
for(int j=,ytk;j<=tot;++j){
ytk=i*P[j];if(ytk>=N)break;
vis[ytk]=;if(i%P[j]==)break;
}
}
} inline int QPow(int d,int z,int res=){
for(;z;z>>=,d=1ll*d*d%Mod)
if(z&)res=1ll*res*d%Mod;
return res;
} inline void solve(){
int i=,j=;T.clear();
while(i<=cnt && j<=top){
if(Y[i].pre<=opt[j].tr)
T.update(Y[i].id,Y[i].val),++i;
else{
int id=opt[j].id;
if(opt[j].kind==)Ans[id]=1ll*Ans[id]*T.query(opt[j].r)%Mod;
else Ans[id]=1ll*Ans[id]*QPow(T.query(opt[j].r),Mod-)%Mod;
++j;
}
}
while(j<=top){
int id=opt[j].id;
if(opt[j].kind==)Ans[id]=1ll*Ans[id]*T.query(opt[j].r)%Mod;
else Ans[id]=1ll*Ans[id]*QPow(T.query(opt[j].r),Mod-)%Mod;
++j;
}
} int main()
{
freopen(FILE".in","r",stdin);
freopen(FILE".out","w",stdout);
n=gi();m=gi();prepare();
for(int i=;i<=n;++i)A[i]=gi();
for(int i=;i<=n;++i){
int ytk=A[i];
for(int j=;P[j]<=ytk/P[j];++j)
if(ytk%P[j]==){
W[++cnt]=P[j];ytk/=P[j];V[cnt]=P[j];
while(ytk%P[j]==)
++cnt,W[cnt]=W[cnt-]*P[j],V[cnt]=P[j],ytk/=P[j];
}
if(ytk>)W[++cnt]=ytk,V[cnt]=ytk;
ED[i]=cnt;
}
for(int i=;i<=cnt;++i)pre[i]=bin[W[i]],bin[W[i]]=i;
for(int i=;i<=cnt;++i)Y[i]=Pair(pre[i],i,V[i]);
sort(Y+,Y+cnt+);
for(int i=;i<=m;++i){
int l=gi(),r=gi();Ans[i]=;
opt[++top]=(Data){ED[r],ED[l-],,i};
opt[++top]=(Data){ED[l-],ED[l-],-,i};
}
sort(opt+,opt+top+);solve();
for(int i=;i<=m;++i)printf("%d\n",Ans[i]);
return ;
}

树状数组

 

51Nod1203 2012集训队答辩 JZPLCM的更多相关文章

  1. CTSC 2018酱油记

    Day0 5.5 花了一上午的时间把codechef div2的前四题切了,又在zbq老司机的指导下把第五题切了 中午12:00 gryz电竞组从机房出发,临走的时候看到很多学长挺恋恋不舍的,毕竟可能 ...

  2. CTSC&APIO2018游记

    Day-1 布吉岛干什么,好像只看了Splay Day0 再次布吉岛干什么,好像也只看了Splay 然后上了火车 wc没买方便面,只能吃40元的盒饭 半夜睡不着,那应该是我太菜了 Day1 九点下火车 ...

  3. ctsc2018

    day1: 8:20分还不知道考场在哪给ccf差评 8:30开始看题 第一题感觉是个模拟啊 很烦 瞄了一眼第二题第三题题意挺简单的啊感觉还不错 然后开始仔细看t1 然后我发现好像可以退狮子 应该是个数 ...

  4. CTSC2017酱油记

    恩..又是一篇酱油记.. 自从SHTSC完之后都在复习地理高考..根本没有刷题.. 于是就来CTSC了..因为奇怪的实验考..APIO又不能参加..只能拿一块Fe了.. DAY0 恩..不存在DAY0 ...

  5. 开始是为了结束,结束是新的开始——NOI 2020 游记

    Day 0 报道日 晚上的时候我们的教练给我们做考前动员.给我们讲:NOI的五个小时需要认真的规划,不能被T1打乱节奏.他让我们思考明天的策略,把可能出问题的地方都想清楚. 结果后来,宿管给我测体温, ...

  6. BZOJ_2622_[2012国家集训队测试]深入虎穴_最短路

    BZOJ_2622_[2012国家集训队测试]深入虎穴_最短路 Description 虎是中国传统文化中一个独特的意象.我们既会把老虎的形象用到喜庆的节日装饰画上,也可能把它视作一种邪恶的可怕的动物 ...

  7. [国家集训队2012]middle

    http://cogs.pro:8080/cogs/problem/problem.php?pid=1763 二分答案x 把区间内>=x的数设为1,<x的数设为-1 左端点在[a,b]之间 ...

  8. 【BZOJ2622】[2012国家集训队测试]深入虎穴 次短路

    [BZOJ2622][2012国家集训队测试]深入虎穴 Description 虎是中国传统文化中一个独特的意象.我们既会把老虎的形象用到喜庆的节日装饰画上,也可能把它视作一种邪恶的可怕的动物,例如“ ...

  9. [国家集训队2012]JZPFAR

    [国家集训队2012]JZPFAR 题目 平面上有n个点.现在有m次询问,每次给定一个点(px, py)和一个整数k,输出n个点中离(px, py)的距离第k大的点的标号.如果有两个(或多个)点距离( ...

随机推荐

  1. 问题(一)---线程池,锁、堆栈和Hashmap相关

    一.线程池: 多线程技术主要解决处理器单元内多个线程执行的问题,它可以显著减少处理器单元的闲置时间,增加处理器单元的吞吐能力. 假设一个服务器完成一项任务所需时间为:T1 创建线程时间,T2 在线程中 ...

  2. 大数据基础篇(一):联机分析处理(OLAP) 与 联机事务处理(OLTP)

    联机事务处理(OLTP) OLTP也称实时系统(Real Time System),支持事务快速响应和大并发,这类系统典型的有ATM机(Automated Teller Machine)系统.自动售票 ...

  3. A workaround to change shared memory size for Docker containers in AWS ECS

    Issue Because of not supporting to specify the following docker run parameter, containers in ECS can ...

  4. SaltStack 部署案例 02

    远程执行 salt '*' state.sls apache '*':代表所有主机 state.sls :是一个模块 apache : 状态 ,表示需要部署的内容,后缀.sls YAML:三板斧 1. ...

  5. js 获取每月有几周,根据年月周获取该周从周一到周日的日期等方法

    本文基于react-native 本人在用react-native写一个关于课程表的APP时需要课程表按照日期周期显示,网上查了许多方法,都没有达到自己想要的效果,根据一些方法的参考,再根据自己思维写 ...

  6. [PHP]Symfony or Laravel 在 console 中结合 Workerman

    在web框架的console中,命令不再是直接指定入口文件,如以往 php test.php start,而是类似 php app/console do 的形式. workerman 对命令的解析是 ...

  7. react入门到进阶(三)

    一.react样式 1.内联样式 在以前写html+css的时候,引入css的时候有一种方法就是内联,而在react中又有些不一样,样式是用变量的形式,如下 const styleComponentH ...

  8. 上班打卡--- 通过批处理命令执行jar文件来记录上班时间

    如果 一个程序员要记录自己上班工作时间的话 ,还需要靠手动去记录, 那就有点 不够范了, 程序员自然要有自己的极客范儿 , 下面就跟我一起来(zhuangbi); 先列一下整体的步骤: 1: 先做一个 ...

  9. gis电子地图开发公司面临的挑战和机遇

    从上个世纪90年代开始电子地图应用就已经收到人们的关注,但是由于时代的局限性和市场经济发展的不成熟.地理信息系统系统的应用并没有得到很好的利用.只有少数的国家机构和军事系统才能够使用这些应用.随着技术 ...

  10. 学校的c++程序课程设计(简单的写法 并无太多c++的特色)

    好久没更新博客了,最近一直在忙,花了一天时间做出这个简陋版的课程设计, 为了储存,也为了更新,所以于今天更新我的博客. 我选的课程设计题目如下: 某某公司的设备管理系统 功能及要求描述: (1)公司主 ...