「杂题乱刷2」CF311D
题目链接
解题思路
实际上不难。
注意到特殊的模数,考虑是否会出现循环节。
然后打表发现循环节长度为 \(48\)。
那么我们显然使用分快维护块内乘了几次即可,因为有 \(48\) 的极小循环节。
块长取 \(50\) 显然是优秀的。
参考代码
ll n,q;
ll a[100010][50];
ll sq;
ll L[100010],R[100010];
ll b[100010];
ll now[100010];
ll S[100010][50];
ll f(ll x)
{
x%=mod;
return x*x%mod*x%mod;
}
ll opt,l,r;
void _clear(){}
void solve()
{
_clear();
cin>>n;
forl(i,1,n)
{
cin>>a[i][0];
a[i][0]%=mod;
forl(j,1,47)
a[i][j]=f(a[i][j-1]);
}
sq=50;
forl(i,1,n)
{
L[i]=R[i-1]+1,
R[i]=min(n,sq*i);
now[i]=0;
forl(j,L[i],R[i])
{
b[j]=i;
forl(k,0,47)
S[i][k]=(S[i][k]+a[j][k])%mod;
// cout<<a[j][k]<<'?';
}
// cout<<S[i][0]<<' ';
if(R[i]==n)
break;
}
cout<<endl;
// forl(i,1,n)
// cout<<b[i]<<' ';
// cout<<endl;
cin>>q;
forl(_,1,q)
{
cin>>opt>>l>>r;
if(opt==2)
{
if(b[l]==b[r])
{
forl(i,l,r)
{
a[i][0]=f(a[i][0]);
forl(j,1,47)
a[i][j]=f(a[i][j-1]);
}
forl(j,0,47)
S[b[l]][j]=0;
forl(j,L[b[l]],R[b[l]])
forl(k,0,47)
S[b[l]][k]=(S[b[l]][k]+a[j][k])%mod;
continue;
}
forl(i,l,R[b[l]])
{
a[i][0]=f(a[i][0]);
forl(j,1,47)
a[i][j]=f(a[i][j-1]);
}
forl(j,0,47)
S[b[l]][j]=0;
forl(j,L[b[l]],R[b[l]])
forl(k,0,47)
S[b[l]][k]=(S[b[l]][k]+a[j][k])%mod;
forl(i,L[b[r]],r)
{
a[i][0]=f(a[i][0]);
forl(j,1,47)
a[i][j]=f(a[i][j-1]);
}
forl(j,0,47)
S[b[r]][j]=0;
forl(j,L[b[r]],R[b[r]])
forl(k,0,47)
S[b[r]][k]=(S[b[r]][k]+a[j][k])%mod;
forl(i,b[l]+1,b[r]-1)
now[i]=(now[i]+1)%48;
}
else
{
if(b[l]==b[r])
{
ll sum=0;
forl(i,l,r)
sum=(sum+a[i][now[b[l]]])%mod;
cout<<sum<<endl;
continue;
}
ll sum=0;
forl(i,l,R[b[l]])
sum=(sum+a[i][now[b[l]]])%mod;
// cout<<a[i][now[b[l]]]<<'>';
forl(i,L[b[r]],r)
sum=(sum+a[i][now[b[r]]])%mod;
// cout<<a[i][now[b[r]]]<<'?';
forl(i,b[l]+1,b[r]-1)
sum=(sum+S[i][now[i]])%mod;
// cout<<S[i][now[i]]<<'&';
cout<<sum<<endl;
}
}
}

浙公网安备 33010602011771号