题目描述
给出一个集合lucky
已知这个集合只可能包含2~6的整数
有一个集合L
一个元素i属于L当且仅当i属于lucky或者i=jk且j,k都属于L
我们这样定义一个集合的F值
F(S)=F(S^d)+F(S^d)*qd+d d为集合中最大的一个数 S^d表示S去掉d后的集合
每次给定a,b
要求求出满足被L的第a项A整除且整除L的第b项B的集合的F值
Solution
F({a,b})=qab+a+b
向上面那样多展开几层,就可以得到这样的一个的F的计算公式
然而并无用。。我想到的时候还以为。。。
F(S)=q*F(S^d)*F({d})+F(S^d)
在做的时候,发现所有子集的d的乘积乘上q^(size-1)的和就是答案
好像没有用?
但qF(S)+1有很优美的形式//自行YY。。。
若S=A+B//+在这里表示集合的并
我们发现qF(S)+1=(qF(A)+1)*(qF(B)+1)
得F(S)=qF(A)F(B)+F(A)+F(B)
如果lucky={2}那么显然就是2^(a~b)的连续的一段
询问连续一段的可并信息?Seg走起
至于为什么是2~6,而没有7这个质数就自己想去吧显而易见了
2 3 5三个线段树套一起,那真是。。。
还有一个优化 若无2,3,4 6可以看成一个质数
暴力处理出L的前1e5项,//具体使用priority_queue实现
据说这题可以用一种映射的方式免除插入而在建树的时候统计答案
写的时候,念念不忘template,然后就写成了这个鬼样子
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<queue>
#include<cctype>
using namespace std;
namespace IO{
const int ios=1<<17;
char R[ios],*Rc=R,*RB=R;
inline int gec(){return(Rc==RB&&(RB=(Rc=R)+fread(R,1,ios,stdin),Rc==RB))?EOF:*Rc++;}
template<typename Tp>inline int read(Tp&A){
static int c,sg;c=gec();sg=0;A=0;
while(!isdigit(c)&&c!=EOF)sg|=(c=='-'),c=gec();
if(c==EOF)return EOF;
while(isdigit(c))A=(A<<3)+(A<<1)+(c^'0'),c=gec();
return A=sg?-A:A,0;
}
}
using IO::gec;using IO::read;
int P,bitQ,A1,A2,A3;
namespace Seg{
template<typename Tp>inline void upd(Tp&a,const Tp&b){a=((1LL*a*b)%P*bitQ+a+b)%P;}
int newValue,res;
template<typename BT,typename AT,typename QT,typename subtype,const int Trs>struct Seg{
BT B;AT A;QT Q;
subtype sub[Trs];
int lc[Trs],rc[Trs];
int Lc,Rc,NO,pos;
void ins(int&i,const int&l,const int&r){
if(!i)i=++NO,sub[i]=0;
A(sub[i]);
if(l<r){
int mid=(l+r)>>1;
if(pos<=mid)ins(lc[i],l,mid);
else ins(rc[i],mid+1,r);
}
}
void bld(int&i,const int&l,const int&r){
i=++NO;
B(sub[i]);
if(l<r){
int mid=(l+r)>>1;
bld(lc[i],l,mid);
bld(rc[i],mid+1,r);
}
}
void Qry(const int&i,const int&l,const int&r){
if(!i)return;
if(Lc<=l&&r<=Rc)return Q(sub[i]);
int mid=(l+r)>>1;
if(Lc<=mid)Qry(lc[i],l,mid);
if(Rc>mid)Qry(rc[i],mid+1,r);
}
};
struct B3{void operator()(int&sub)const{sub=0;}};
struct Q3{void operator()(int sub)const{return upd(res,sub);}};
struct D3{void operator()(int&sub)const{return upd(sub,newValue);}};
Seg<B3,D3,Q3,int,10000010>T3;
struct B2{void operator()(int&sub)const{T3.bld(sub,0,A3);}};
struct Q2{void operator()(int sub)const{return T3.Qry(sub,0,A3);}};
struct D2{void operator()(int&sub)const{return T3.ins(sub,0,A3);}};
Seg<B2,D2,Q2,int,5000010>T2;
struct B1{void operator()(int&sub)const{T2.bld(sub,0,A2);}};
struct Q1{void operator()(int sub)const{return T2.Qry(sub,0,A2);}};
struct D1{void operator()(int&sub)const{return T2.ins(sub,0,A2);}};
Seg<B1,D1,Q1,int,3000010>T1;
}
namespace NumWork{
const double eps=1e-6;
struct Num{
Num(){}
Num(int a1,int a2,int a3,double ln,long long d):a1(a1),a2(a2),a3(a3),re(ln),val(d%P){}
int a1,a2,a3,val;
double re;
bool operator <(Num A)const{return re>A.re;}
bool operator ==(Num A)const{return val==A.val&&fabs(re-A.re)<eps;}
bool judge(Num A)const{return a1<=A.a1&&a2<=A.a2&&a3<=A.a3;}
Num operator *(Num A){return Num(a1+A.a1,a2+A.a2,a3+A.a3,re+A.re,1ll*val*A.val);};
};
priority_queue<Num> HP;
static const int limit=100000;
int pr[10],prpr,Counter,OK[10],times[10][10],state,HLJ;
Num bit[10],que[limit+5];
// #define read(a) scanf("%d",&a)
void init(){
freopen("volunteer.in","r",stdin);
freopen("volunteer.out","w",stdout);
for(int id=2;id<=6;id++){
read(OK[id]);
state|=(OK[id]<<(id-2));
}
if(state==16){
pr[prpr++]=6;
}else if(state==24){
pr[prpr++]=5;pr[prpr++]=6;
}else{
if(state&21)pr[prpr++]=2;
if(state&18)pr[prpr++]=3;
if(state&8)pr[prpr++]=5;
}
read(P);read(bitQ);
}
void work(){
for(int id=2;id<=6;id++){
if(OK[id]){
int tmp=id;
for(int i=0;i<prpr;i++)
while(tmp%pr[i]==0)tmp/=pr[i],times[id][i]++;
HP.push(bit[id]=Num(times[id][0],times[id][1],times[id][2],log(id),id));
}
}
while(Counter<limit){
Num tmp;
while(tmp=HP.top(),Counter&&que[Counter]==tmp)
HP.pop();
HP.pop();
que[++Counter]=tmp;
A1=max(A1,tmp.a1);
A2=max(A2,tmp.a2);
A3=max(A3,tmp.a3);
for(int id=2;id<=6;id++){
if(OK[id])HP.push(tmp*bit[id]);
}
}
using namespace Seg;
//T1.bld(HLJ,0,A1);
for(int i=1;i<=Counter;i++){
T1.pos=que[i].a1;
T2.pos=que[i].a2;
T3.pos=que[i].a3;
newValue=que[i].val;
T1.ins(HLJ,0,A1);
}
}
void solve(){
using namespace Seg;
int QwQ,a,b;
read(QwQ);
while(QwQ--){
read(a);read(b);
Num A=que[a],B=que[b];
if(!A.judge(B))puts("0");
else{
T1.Lc=A.a1,T1.Rc=B.a1;
T2.Lc=A.a2,T2.Rc=B.a2;
T3.Lc=A.a3,T3.Rc=B.a3;
res=0;T1.Qry(HLJ,0,A1);
printf("%d\n",res);
}
}
}
}
int main(){
NumWork::init();
NumWork::work();
NumWork::solve();
return 0;
}