题目大意:中文题自己看
首先phi[i] = i * (1 - p1) ... * (1 - pn)
由于每一个质因数p只用了一次,所以对区间做HH 的项链就好了.
PS: 我真是太弱了,差点写吐了QAQ...
#include <stdio.h>
#include <cstring>
#include <iostream>
#include <algorithm>
typedef long long ll;
#define N 1000000UL
#define MAXN 50005UL
#define mod 1000777UL
int n,Q,prime[1000005],tot,last[1000005],val[MAXN];
bool _prime[1000005];
ll Ans,use[1000005],fac[MAXN];
template<typename _t>
inline _t read(){
_t x=0,f=1;
char ch=getchar();
for(;ch>'9'||ch<'0';ch=getchar())if(ch=='-')f=-f;
for(;ch>='0'&&ch<='9';ch=getchar())x=x*10+(ch^48);
return x*f;
}
inline ll qpow(ll x,ll k){
ll Ans = 1;
for(;k;k>>=1,x = 1ll * x * x % mod) if(k&1) Ans = Ans * x % mod;
return Ans;
}
int first[1000005],e = 1;
struct edge{
int u,v,next;
}a[3000005];
inline void push(int u,int v){
a[e].u=u;a[e].v=v;a[e].next=first[u];first[u]=e++;
}
inline void init(){
for(int i = 2;i<=N;i++) {
if(!_prime[i]) {
prime[++tot] = i;
for(int j = i;j<=N;j+=i){
_prime[j] = 1;
push(j,tot);
}
}
}
for(int i = 1;i<=tot;i++) use[i] = 1ll * (prime[i]-1) * qpow(prime[i],mod-2) % mod;
}
namespace CMT{
int root[MAXN],cnt;
struct node{
int l,r; ll sum;
}tree[MAXN*100];
inline void build(int &o,int l,int r){
o = ++ cnt; tree[o].sum = 1;
if(l == r) return;
register int mid = l + r >> 1;
build(tree[o].l,l,mid);build(tree[o].r,mid+1,r);
}
inline void Update(int &o,int old,int l,int r,int x,ll val){
o = ++ cnt; tree[o] = tree[old];
tree[o].sum = tree[old].sum * val % mod;
if(l == r) return;
register int mid = l + r >> 1;
if(x<=mid) Update(tree[o].l,tree[old].l,l,mid,x,val);
else Update(tree[o].r,tree[old].r,mid+1,r,x,val);
}
inline ll Query(int o,int l,int r,int x,int y){
if(x<=l&&r<=y) return tree[o].sum;
register int mid = l + r >> 1; ll Ans = 1;
if(x<=mid) Ans = Ans * Query(tree[o].l,l,mid,x,y) % mod;
if(mid<y) Ans = Ans * Query(tree[o].r,mid+1,r,x,y) % mod;
return Ans;
}
}
using namespace CMT;
inline void work(int x,int id){
int num = root[id - 1];
ll sum = 1;
for(int i = first[x];i;i=a[i].next) {
if(x%prime[a[i].v] == 0){
while(x % prime[a[i].v] == 0) x /= prime[a[i].v];
if(last[prime[a[i].v]]) Update(num,num,1,n,last[prime[a[i].v]],qpow(use[a[i].v],mod-2));
last[prime[a[i].v]] = id;
sum = sum * use[a[i].v] % mod;
}
}
Update(root[id],num,1,n,id,sum);
}
inline void Query(){
register int l = read<int>() ^ Ans , r = read<int>() ^ Ans;
Ans = Query(root[r],1,n,l,r);
Ans = Ans * fac[r] % mod * qpow(fac[l-1],mod-2) % mod;
printf("%lld\n",Ans);
}
int main(){
init();
n = read<int>();Q = read<int>(); fac[0] = 1;build(root[0],1,n);
for(int i = 1;i<=n;i++) val[i] = read<int>(),fac[i] = fac[i-1] * val[i] % mod;
for(int i = 1;i<=n;i++) work(val[i],i);
while(Q --) Query();
return 0;
}