1 条题解
-
0
自动搬运
来自洛谷,原作者为

znszns
**搬运于
2025-08-24 22:52:05,当前版本为作者最后更新于2023-10-30 14:57:47,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
P9816 少项式复合幂题解
分做法
先注意题目加粗的字,提示我们应该考虑 的范围。
预处理
显然 ,所以考虑预处理 ,, 范围为 到 ,时间复杂度为 。
查询操作
直接一次一次跳,暴力跳 次找到 ,时间复杂度为 。
代码
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int N=1e5+10; int m,q; ll mod,f[N],a[N],b[N]; ll qpow(ll x,ll y) { ll res=1; for(;y;y>>=1,x=x*x%mod) { if(y&1) res=res*x%mod; } return res; } int main() { scanf("%d%d%lld",&m,&q,&mod); for(int i=1;i<=m;i++) scanf("%lld%lld",&a[i],&b[i]); for(int i=0;i<mod;i++) { for(int j=1;j<=m;j++) { f[i]=(f[i]+a[j]*qpow(i,b[j])%mod)%mod; } } ll x,y,ans; for(int i=1;i<=q;i++) { scanf("%lld%lld",&x,&y); ans=f[x%mod]; for(int j=2;j<=y;j++) { ans=f[ans]; } cout<<ans<<endl; } return 0; }分做法
可以发现查询操作若为 是可以过的,于是先求出 的二进制表示,比如说要跳 次,相当于先跳 次,再跳 次。
预处理
用 表示 跳 次的结果,转移为 。
查询操作
把 用二进制表示,最低位是第 位,若第 位为 ,设当前答案为 , 则跳到 ,表示跳了 次,最后输出 即可。
代码
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int N=1e5+10,M=25; int m,q; ll mod,f[N][M],a[N],b[N]; ll qpow(ll x,ll y) { ll res=1; for(;y;y>>=1,x=x*x%mod) { if(y&1) res=res*x%mod; } return res; } int main() { scanf("%d%d%lld",&m,&q,&mod); for(int i=1;i<=m;i++) scanf("%lld%lld",&a[i],&b[i]); for(int i=0;i<mod;i++) { for(int j=1;j<=m;j++) { f[i][0]=(f[i][0]+a[j]*qpow(i,b[j])%mod)%mod; } } for(int j=1;j<M;j++) { for(int i=0;i<mod;i++) { f[i][j]=f[f[i][j-1]][j-1]; } } ll x,y,ans,cnt; for(int i=1;i<=q;i++) { scanf("%lld%lld",&x,&y); cnt=0; ans=x%mod; while(y) { if(y&1) ans=f[ans][cnt]; cnt++; y>>=1; } cout<<ans<<endl; } return 0; }
- 1
信息
- ID
- 9325
- 时间
- 1000ms
- 内存
- 512MiB
- 难度
- 4
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者