传送门

一开始理解错题意了……还以为是两个子序列相同的话只算一次……结果是子序列里相同的元素只算一次……

对于一个区间\([l,r]\),设其中\(x\)出现了\(k\)次,那么它的贡献就是它的权值乘上包含它的序列个数,即\(2^{r-l+1}-2^{r-l+1-k}\),总的序列个数减去不包含它的序列个数。因为\(x\)和\(k\)无关,所以只要统计出现次数为\(k\)的所有\(x\)的总和即可

不同的\(k\)最多只有\(\sqrt n\)个,于是用个邻接表之类的东西维护一下,然后每次询问就可以\(O(\sqrt n)\)解决了

然而因为模数不同,\(2\)的次幂不能预处理,于是可以设一个\(S=\sqrt n\),然后用\(O(\sqrt n)\)预处理出\(2^0,2^1,2^2,...,2^S\)和\(2^S,2^{2S},2^{3S},...\),这样每一个\(2\)的次幂都能\(O(1)\)求得了

然后用莫队维护一下询问就好了,总的时间复杂度为\(O(n\sqrt n)\)

//minamoto
#include<bits/stdc++.h>
#define R register
#define ll long long
#define fp(i,a,b) for(R int i=a,I=b+1;i<I;++i)
#define fd(i,a,b) for(R int i=a,I=b-1;i>I;--i)
#define go(u) for(int i=head;i;i=nxt[i])
using namespace std;
char buf[1<<21],*p1=buf,*p2=buf;
inline char getc(){return p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++;}
int read(){
R int res,f=1;R char ch;
while((ch=getc())>'9'||ch<'0')(ch=='-')&&(f=-1);
for(res=ch-'0';(ch=getc())>='0'&&ch<='9';res=res*10+ch-'0');
return res*f;
}
char sr[1<<21],z[20];int C=-1,Z=0;
inline void Ot(){fwrite(sr,1,C+1,stdout),C=-1;}
void print(R int x){
if(C>1<<20)Ot();if(x<0)sr[++C]='-',x=-x;
while(z[++Z]=x%10+48,x/=10);
while(sr[++C]=z[Z],--Z);sr[++C]='\n';
}
const int N=1e5+5;
int n,m,rt[N],a[N],ans[N],S,Pre[N],nxt[N],vis[N],cnt[N],head=0;
int P,f[1005],g[1005];
ll sum[N];
struct node{
int l,r,p,id;
inline bool operator <(const node &b)const
{return rt[l]==rt[b.l]?rt[b.l]&1?r<b.r:r>b.r:l<b.l;}
}q[N];
inline void add(R int x){nxt[x]=head,Pre[head]=x,head=x,Pre[x]=0;}
inline void del(R int x){x==head?head=nxt[x]:(nxt[Pre[x]]=nxt[x],Pre[nxt[x]]=Pre[x]);}
void update(R int x,R int y){
if(cnt[a[x]]){
sum[cnt[a[x]]]-=a[x];
if(--vis[cnt[a[x]]]==0)del(cnt[a[x]]);
}cnt[a[x]]+=y;
if(cnt[a[x]]){
sum[cnt[a[x]]]+=a[x];
if(++vis[cnt[a[x]]]==1)add(cnt[a[x]]);
}
}
inline int add(R int x,R int y){return x+y>=P?x+y-P:x+y;}
inline int dec(R int x,R int y){return x-y<0?x-y+P:x-y;}
inline int mul(R int x,R int y){return 1ll*x*y-1ll*x*y/P*P;}
void init(R int n){
f[0]=g[0]=1;
fp(i,1,S)f[i]=add(f[i-1],f[i-1]);
fp(i,1,n/S)g[i]=mul(g[i-1],f[S]);
}
inline int ksm(R int n){return mul(g[n/S],f[n%S]);}
int query(int l,int r,int p){
P=p,init(r-l+1);int res=0;
go(i)res=add(res,mul(sum[i]%P,dec(ksm(r-l+1),ksm(r-l+1-i))));
return res;
}
int main(){
// freopen("testdata.in","r",stdin);
n=read(),m=read(),S=sqrt(n);
fp(i,1,n)a[i]=read(),rt[i]=(i-1)/S+1;
fp(i,1,m)q[i].l=read(),q[i].r=read(),q[i].p=read(),q[i].id=i;
sort(q+1,q+1+m);int l=1,r=0;
fp(i,1,m){
while(l>q[i].l)update(--l,1);
while(r<q[i].r)update(++r,1);
while(l<q[i].l)update(l++,-1);
while(r>q[i].r)update(r--,-1);
ans[q[i].id]=query(q[i].l,q[i].r,q[i].p);
}fp(i,1,m)print(ans[i]);return Ot(),0;
}

P5072 [Ynoi2015]盼君勿忘的更多相关文章

  1. 洛谷:P5072 [Ynoi2015]盼君勿忘

    原题地址:https://www.luogu.org/problem/P5072 题目简述 给定一个序列,每次查询一个区间[l,r]中所有子序列分别去重后的和mod p 思路 我们考虑每个数的贡献.即 ...

  2. 洛谷P5072 [Ynoi2015]盼君勿忘 [莫队]

    传送门 辣鸡卡常题目浪费我一下午-- 思路 显然是一道莫队. 假设区间长度为\(len\),\(x\)的出现次数为\(k\),那么\(x\)的贡献就是\(x(2^{len-k}(2^k-1))\),即 ...

  3. 【题解】Luogu P5072 [Ynoi2015]盼君勿忘

    众所周知lxl是个毒瘤,Ynoi道道都是神仙题,题面好评 原题传送门 一看这题没有修改操作就知道这是莫队题 我博客里对莫队的简单介绍 既然是莫队,我们就要考虑每多一个数或少一个数对答案的贡献是什么 假 ...

  4. Luogu P5072 [Ynoi2015]盼君勿忘

    题意 给定一个长度为 \(n\) 的序列 \(a\) 和 \(m\) 次询问,第 \(i\) 次询问需要求出 \([l_i,r_i]\) 内所有子序列去重之后的和,对 \(p_i\) 取模. \(\t ...

  5. [Ynoi2015]盼君勿忘

    题目大意: 给定一个序列,每次查询一个区间\([l,r]\)中所有子序列分别去重后的和\(\bmod p\)(每次询问模数不同). 解题思路: 在太阳西斜的这个世界里,置身天上之森.等这场战争结束之后 ...

  6. 【洛谷5072】[Ynoi2015] 盼君勿忘(莫队)

    点此看题面 大致题意: 一个序列,每次询问一个区间\([l,r]\)并给出一个模数\(p\),求模\(p\)意义下区间\([l,r]\)内所有子序列去重后值的和. 题意转化 原来的题意看起来似乎很棘手 ...

  7. Luogu5072 [Ynoi2015]盼君勿忘 【莫队】

    题目描述:对于一个长度为\(n\)的序列,\(m\)次询问\(l,r,p\),计算\([l,r]\)的所有子序列的不同数之和\(\mathrm{mod} \ p\). 数据范围:\(n,m,a_i\l ...

  8. EC笔记:第二部分:12、复制对象时勿忘其每一个成分

    EC笔记:第二部分:12.复制对象时勿忘其每一个成分 1.场景 某些时候,我们不想使用编译器提供的默认拷贝函数(包括拷贝构造函数和赋值运算符),考虑以下类定义: 代码1: class Point{ p ...

  9. EC读书笔记系列之7:条款12 复制对象时勿忘其每一个成分

    记住: ★copying函数应确保复制“对象内的所有成员变量”及“所有base class成分” ★不要尝试以某个copying函数实现另一个copying函数.应该将共同机能放进第三个函数中,并由两 ...

随机推荐

  1. bsp开发之驱动开发

    驱动程序是可以管理虚拟设备或者物理设备,协议,服务等得软件模块,操作系统仅仅有通过驱动程序才干訪问硬件.针对windows ce开发设备驱动.就是通过platform builder创建一个新的平台, ...

  2. ruby rails

    http://www.zhihu.com/question/19552402   作者:陈振宇链接:http://www.zhihu.com/question/19552402/answer/1236 ...

  3. const成员函数总结

    const 成员函数: 类的成员函数后面加 const,表明这个函数不会对这个类对象的数据成员(准确地说是非静态数据成员)作不论什么改变. 在设计类的时候.一个原则就是对于不改变数据成员的成员函数都要 ...

  4. java中类加载顺序(深入Java)

    未涉及虚拟机 0.<init>与<clinit>的区别 1.类的加载过程 2.类的使用方式 3.类的加载来源 4.重载之泛型参数不同可以吗 5.参考 引子 记得上次中秋一哥们写 ...

  5. 通过反射调用一个单列的方法(单列必须有“getInstance”方法)

    Class<?> _clazz = Class.forName(_clazzName); if (_clazz != null) { Method _getInstance = _claz ...

  6. 区分虚拟机和machine simulator

    1 虚拟机和machine simulator的不同 虚拟机是让多个操作系统同时共用现有的硬件架构,它不会模拟新的硬件架构.qemu这样的模拟器是模拟新的硬件架构,这个架构和host不同.

  7. spring cloud-服务注册

    正常的服务模块,注册到注册中心,让别的服务发现,调用服务 创建“服务提供方” 下面我们创建提供服务的客户端,并向服务注册中心注册自己. 假设我们有一个提供计算功能的微服务模块,我们实现一个RESTfu ...

  8. futimens函数的使用【学习笔记】

    #include "apue.h" #include <fcntl.h> int main(int argc,char *argv[]) { int i,fd; str ...

  9. Spring Boot2.0之 整合Redis集群

    项目目录结构: pom: <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http:// ...

  10. iOS多线程全套:线程生命周期,多线程的四种解决方案,线程安全问题,GCD的使用,NSOperation的使用

    目的 本文主要是分享iOS多线程的相关内容,为了更系统的讲解,将分为以下7个方面来展开描述. 多线程的基本概念 线程的状态与生命周期 多线程的四种解决方案:pthread,NSThread,GCD,N ...