解题报告:
Consider a number x. If we apply an assignmentx = x3,x becomes x3. If we apply such assignment once more, we will get(x3)3 = x32. If we apply such assignmentk times, we will get x3k.
Thus, we can get such a sequence a0 = x, a1 = x3, a2 = x32, ..., ak = x3k, ....
Consider a prime p. From Fermat's Little Theorem, we can getxp - 1 = 1(mod p). Further more, we can get xy = xymod(p - 1)(modp), here amod b means the remainder
of a divided by b.
推论证明:
x^(n(p-1))=1 mod p
Fortunately, 348 = 1(mod(95542721 - 1)), thus, x3k = x3kmod48(modp). In other words, ak = ak + 48, which means the cycle of the sequence isT = 48.
Let's come back to the topic. Each time we run a 1-type query, for every i in the range [l, r], we apply such an assignmentai = ai3. At any moment somei has been applied 48 times such assignments, we can consider thisi hasn't been applied any assignments before.
We can use segment tree to solve this problem. Every node of the segment tree maintains some information: the times that we applied assignments in the node's whole range(it's a lazy tag), current sum of the node's corresponding range and the sum of the node's range after we applied assignments k(1 ≤ k < 48) times.
In such a way, we can solve the problem in O(n·T + q·T·logn) time.
If you do not realize how to maintain the segment tree clearly, you can view the code3782263.
贴个我的超时代码:下附神牛代码。
/*
线段树:使用延迟标记,下传叠加 。
使用 mark 标记该节点下的子节点是否存在没有处理的 数值、
此题还有一定的数论知识,详细看上文解题报告。
*/
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
#define mod 95542721
#define manx 100009
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
__int64 a[manx],root[manx<<2],sum;
int s[manx<<2];
bool mark[manx<<2];
void up(int rt) {
root[rt]=root[rt<<1]+root[rt<<1|1];
if(mark[rt<<1] || mark[rt<<1|1]) mark[rt]=1;
else mark[rt] = 0;
}
void make(int l,int r,int rt){
s[rt] = 0;
mark[rt] = 0;
if(l==r){ root[rt]=a[l]; return ;}
int mid=(l+r)>>1;
make(lson);
make(rson);
up(rt);
}
void update(int L,int R,int l,int r,int rt){
mark[rt]=1;
if(L<=l && r<=R) { s[rt]++; return; }
int mid =(l+r)>>1;
if(R<=mid) update(L,R,lson);
else if(L>mid) update(L,R,rson);
else {
update(L,mid,lson);
update(mid+1,R,rson);
}
}
void query(int L,int R,int l,int r,int rt){
if(L<=l && r<=R) { sum+=root[rt]; sum%=mod; return ; }
int mid = (l+r)>>1;
if(R<=mid) query(L,R,lson);
else if(L>mid) query(L,R,rson);
else {
query(L,mid,lson);
query(mid+1,R,rson);
}
}
void operate(int rt){
for(int i=1;i<=s[rt];i++)
root[rt]=root[rt]*root[rt]%mod*root[rt]%mod;
s[rt]=0;
mark[rt]=0;
return ;
}
void down(int L,int R,int l,int r,int rt){
if(!mark[rt]) return;
if(l==r && l<=R && l>=L ) { operate(rt); return; }
if(l==r) return;
if(s[rt]) {
s[rt<<1]+=s[rt];
s[rt<<1|1]+=s[rt];
s[rt]=0;
mark[rt<<1] = mark[rt<<1|1] = 1;/
}
int mid=(l+r)>>1;
if(R<=mid) down(L,R,lson);
else if(L>mid) down(L,R,rson);
else {
down(L,mid,lson);
down(mid+1,R,rson);
}
up(rt);
}
int main(){
int n,q;
while(scanf("%d",&n)!=EOF){
for(int i=1;i<=n;i++) scanf("%I64d",&a[i]);
make(1,n,1);
scanf("%d",&q);
int type,l,r;
for(int i=0;i<q;i++){
scanf("%d%d%d",&type,&l,&r);
sum = 0;
if(type==2) update(l,r,1,n,1);
if(type==1) {
down(l,r,1,n,1);
query(l,r,1,n,1);
printf("%I64d\n",sum);
}
}
}
}
/*
8
1 2 3 4 5 6 7 8
12
1 2 5
2 2 5
1 2 5
2 3 6
1 4 7
*/
正确代码:
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<ctime>
#include<iostream>
#include<sstream>
#include<algorithm>
#include<string>
#include<bitset>
#include<vector>
#include<set>
#include<map>
#include<queue>
#include<iomanip>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
typedef pair<int,int> pii;
typedef pair<ld,ld> pdd;
typedef pair<ll,ll> pll;
#define X first
#define Y second
const int MaxN=100010;
const int MOD=95542721;
const int LEN=48;
int n;
int a[MaxN];
struct node
{
node *Lc,*Rc;
int L,R,m;
int p;
int v[LEN];
node (int x,int y)
{
L=x;
R=y;
m=(L+R)>>1;
p=0;
Lc=Rc=0;
memset(v,0,sizeof(v));
}
};
node *root;
int tmp[LEN];
int mod(int x,int MOD)
{
while (x>=MOD) x-=MOD;
return x;
}
void update(node *it)
{
for (int i=0;i<LEN;++i)
it->v[i]=mod(it->Lc->v[i]+it->Rc->v[i],MOD);
}
void clear(node *it)
{
if (!it->p) return;
memcpy(tmp,it->Lc->v,sizeof(tmp));
for (int i=0;i<LEN;++i)
it->Lc->v[i]=tmp[mod(i+it->p,LEN)];
it->Lc->p=mod(it->Lc->p+it->p,LEN);
memcpy(tmp,it->Rc->v,sizeof(tmp));
for (int i=0;i<LEN;++i)
it->Rc->v[i]=tmp[mod(i+it->p,LEN)];
it->Rc->p=mod(it->Rc->p+it->p,LEN);
it->p=0;
}
node *build(int L,int R)
{
node *it=new node(L,R);
if (L<R)
{
it->Lc=build(L,it->m);
it->Rc=build(it->m+1,R);
update(it);
}
else
{
int t=a[L];
for (int i=0;i<LEN;++i)
{
it->v[i]=t;
t=(ll)t*t%MOD*t%MOD;
}
}
return it;
}
int query(node *it,int L,int R)
{
if (it->L==L&&it->R==R)
return it->v[0];
clear(it);
if (R<=it->m)
return query(it->Lc,L,R);
if (L>it->m)
return query(it->Rc,L,R);
return mod(query(it->Lc,L,it->m)+query(it->Rc,it->m+1,R),MOD);
}
void modify(node *it,int L,int R)
{
if (it->L==L&&it->R==R)
{
it->p++;
memcpy(tmp,it->v,sizeof(tmp));
for (int i=0;i<LEN;++i)
it->v[i]=tmp[mod(i+1,LEN)];
return;
}
clear(it);
if (R<=it->m)
modify(it->Lc,L,R);
else if (L>it->m)
modify(it->Rc,L,R);
else
{
modify(it->Lc,L,it->m);
modify(it->Rc,it->m+1,R);
}
update(it);
}
void init()
{
cin>>n;
for (int i=1;i<=n;++i)
{
scanf("%d",&a[i]);
a[i]%=MOD;
}
root=build(1,n);
}
void work()
{
int T;
cin>>T;
while (T--)
{
int flag,x,y;
scanf("%d%d%d",&flag,&x,&y);
if (flag==1)
printf("%d\n",query(root,x,y));
else
modify(root,x,y);
}
}
int main()
{
init();
work();
return 0;
}