1 条题解
-
0
简单题。
考虑把下标转移到 ,那么每次传球实际上是先让 ,之后循环进行 。我们就是要找这个过程中所有 中 最小的。
容易想到把整段整段的 全部取下来,换句话说,我们对 垒前缀和记作 ,那么最终到达的位置实际上可以表示成 。
记最终到达的位置是 ,展开式子有 ,移项得到二元一次不定方程形式:
因为 在 剩余系意义下,所以符号不重要。合法的 只需使得方程有解即可。由裴蜀定理取 ,可知 。
容易发现如果我们已知 ,那么可以轻易做到在线加入 :记忆化地往两边 跳跃,做贡献标记即可,总时间复杂度 。于是按照 离线即可 。
int n,q; int p[N]; int a[N]; bool vis[N]; bool keyn[N]; int res[N]; int ans; int g; vector <int> ofl[N]; void gocheck(int x){ // cout<<"!"<<x<<endl; if(vis[x]) return; vis[x]=1; ans=min(ans,p[x]); gocheck((x+g)%n); gocheck((x+n-g)%n); } int main(){ #ifdef Shun freopen(".in","r",stdin); freopen(".out","w",stdout); #endif ios::sync_with_stdio(false); cin>>n>>q; fr1(i,0,n-1) cin>>p[i]; fr1(i,1,q) cin>>a[i],(a[i]+=a[i-1])%=n; fr1(i,1,q) ofl[__gcd(n,a[i])].pb(i); fr1(i,1,n){ if(ofl[i].empty()) continue; fr1(j,0,n-1) vis[j]=0; fr1(j,1,q) keyn[j]=0; for(auto j:ofl[i]) keyn[j]=1; g=i; ans=1e9; fr1(j,1,q){ gocheck(a[j]); if(keyn[j]){ res[j]=ans; } } } fr1(i,1,q) cout<<res[i]<<' '; ET; } //ALL FOR Zhang Junhao.
- 1
信息
- ID
- 10961
- 时间
- 2000ms
- 内存
- 1024MiB
- 难度
- 10
- 标签
- 递交数
- 1
- 已通过
- 1
- 上传者