题目
给出一个长度为 n n n的环,一个常数 k k k 和 q q q 次询问,每次跳跃会从第 i i i 个点跳到第 ( i + k ) m o d n + 1 (i+k) mod ~n + 1 (i+k)mod n+1 个点(每次都是从第一个点开始跳)。每一个点都有一个权值,记为 a i ai ai。每次询问给出一个 m m m,求 m m m 次跳跃的权值和对 1 e 9 + 7 1e9+7 1e9+7取模。
断点概述:
- 1,同时想到倍增和循环节的思路,可是因为思路不清,使得两个混淆
思想概述:
- 1,倍增处理:跳步数组和合计数组,无需思考mod的情况,思考定义即可
- 2,循环节处理,考虑到mod具有周期性,是一个阿贝尔置换群,直接大段技巧小段暴力
code
int main()
{
int n,k;
scanf("%d%d", &n, &k);
for (int i = 1; i <= n; ++i) {
scanf("%d", v + i);
}
rep(i,1,n)
{
g[0][i]=(i+k)%n+1;
sum[0][i]=v[i];
}
int logn = 31-__builtin_clz(n);
rep(i,1,logn)
{
rep(j,1,n)
{
go[i][j]=go[i-1][go[i-1][j]];
sum[i][j]=modadd(sum[i-1][j],sum[i-1][go[i-1][j]]);
}
}
ll m;
scanf("%lld",&m);
int ans = 0;
int curs= 1;
for(int i=0;m;i++)
{
if(m&(1ll<<i))
{
ans= modadd(ans,sum[i][curs]);
curs= go[i][curs];
m ^= 1ll<<i;
}
}
printf("%d",ans);
}
void get_tim()
{
int cnt= 0;
int pos = 1
while (1)
{
sum[++cnt] = sum[cnt-1]+a[pos];
if(pos == 1) break;
pos += (pos+k) % n + 1;
}
}
int main()
{
ll a=m/cnt,b=m%cnt;
ll ans=(mul(sum[cnt],a,mod)+sum[b])%mod;
}