专栏文章
P7486 「Stoi2031」彩虹 题解
P7486题解参与者 2已保存评论 1
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 1 条
- 当前快照
- 1 份
- 快照标识符
- @miq9ssc0
- 此快照首次捕获于
- 2025/12/04 01:17 3 个月前
- 此快照最后确认于
- 2025/12/04 01:17 3 个月前
题解区查询怎么都是根号 的????
考虑取离散对数,求出模 意义下的原根 ,同时把询问差分成四个前缀,问题变成求:
然后 即为答案。
随便推点式子(下取整省略不写):
只拿 一项的求和出来说,剩下同理。
跟 有关的一项可以 预处理成为 :
然后这个式子就可以整除分块了,预处理 的前缀和即可。
时间复杂度 。
第二项可以 dirichlet 前缀和做到 ,懒得写了。
CPP#define mod 32465177
using mint = modint<mod-1>;
#define g 3
#define maxn 1001000
mint w[maxn];
int mu[maxn];
bool notprime[maxn];
int prime[maxn],cnt;
mint F[maxn],G[maxn],H[maxn],I[maxn],J[maxn];
void getprime(int n) {
mu[1]=notprime[1]=1;
for(int i=2; i<=n; ++i) {
if(not notprime[i]) {
prime[++cnt]=i;
mu[i]=-1;
}
for(int j=1; j<=cnt&&prime[j]*i<=n; ++j) {
notprime[i*prime[j]]=1;
if(i%prime[j]==0) {
mu[i*prime[j]]=0;
break;
}
mu[i*prime[j]]=-mu[i];
}
}
rep(i,1,n)mu[i]*=i;
rep(i,1,n)for(int j=i; j<=n; j+=i)F[j]+=mu[i],G[j]+=w[j/i]*mu[i];
rep(i,1,n)F[i]*=i;
rep(i,1,n)H[i]=H[i-1]+G[i]*i,I[i]=I[i-1]+F[i],J[i]=J[i-1]+F[i]*w[i];
}
int n;
int arr[maxn<<1],m;
int gt(int n) {
int l=1,r;
while(l<=n) {
r=n/(n/l);
arr[m++]=l;
arr[m++]=r+1;
l=r+1;
}
return m;
}
mint W[maxn],Pre[maxn];
mint calc(int l,int r) {
mint res=0;
m=0;
int p=gt(l),q=gt(r);
inplace_merge(arr,arr+p,arr+q);
m=unique(arr,arr+m)-arr;
rep(i,0,m-2) {
int p=arr[i],q=arr[i+1]-1;
int L=l/p,R=r/q;
res-=(H[q]-H[p-1])*(1ll*L*(L+1)/2)*(1ll*R*(R+1)/2);
}
auto wrk=[&](int l,int r)->mint {
mint res=0;
m=0;
int p=gt(l),q=gt(r);
inplace_merge(arr,arr+p,arr+q);
m=unique(arr,arr+m)-arr;
rep(i,0,m-2) {
int p=arr[i],q=arr[i+1]-1;
int L=l/p,R=r/q;
res+=(mint)(1ll*R*(R+1)/2)*(Pre[L]*(I[q]-I[p-1])+(J[q]-J[p-1])*(1ll*L*(L+1)/2));
}
return res;
};
if(l!=r)res+=wrk(l,r)+wrk(r,l);
else res+=wrk(l,r)*2;
return res;
}
void solve() {
int l,r;
cin>>l>>r;
cout<<qp(g,(calc(r,r)-calc(l-1,r)-calc(r,l-1)+calc(l-1,l-1)).val)<<'\n';
}
bool Med;
signed main() {
ios::sync_with_stdio(false);
cin.tie(0),cout.tie(0);
int t;
cin>>t>>n;
for(int i=0,nw=1; i<mod-1; ++i,nw=1ll*nw*g%mod)if(nw<=n)w[nw]=i;
rep(i,1,n)W[i]=W[i-1]+w[i];
rep(i,1,n)Pre[i]=Pre[i-1]+w[i]*i;
getprime(n);
while(t--)solve();
return 0;
}
相关推荐
评论
共 1 条评论,欢迎与作者交流。
正在加载评论...