ABC258E(找循环节)
ABC258E(找循环节)
思路很简单,主要代码很不好写。官方题解的写法很好。
先暴力把每一段长度算出来,然后再环上跳,用一个order数组编号,path寄一下开始结点,之后循环节就很简单能被找到。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<set>
#include<queue>
#include<map>
#include<stack>
#include<string>
#include<random>
#include<iomanip>
#define yes puts("yes");
#define inf 0x3f3f3f3f
#define ll long long
#define linf 0x3f3f3f3f3f3f3f3f
#define ull unsigned long long
#define endl '\n'
#define int long long
#define rep(i,a,n) for(int i = a;i <= n;i++)
#define per(i,n,a) for(int i = n;i >= a;i--)
using namespace std;
mt19937 mrand(random_device{}());
int rnd(int x) { return mrand() % x;}
typedef pair<int,int> PII;
const int MAXN =10 + 2e5 ,mod=1e9 + 7;
void solve()
{
int n,q,x; cin >> n >> q >> x;
vector<int> w(n + n);
rep(i,0,n - 1) cin >> w[i], w[i + n] = w[i];
ll sum = accumulate(w.begin(),w.end(),0ll) / 2;
vector<ll> cnt(n,(x / sum) * n);
x %= sum;
for(int i = 0,j = 0,s = 0;i < n;i ++) {
if(j < i) j = i,s = 0;
while(s < x) s += w[j ++];
cnt[i] += j - i;
s -= w[i];
}
vector<int> path, ord(n,-1);
int loop = -1;
for(int i = 0,id = 0;;id ++) {
if(ord[i] != -1) {
loop = id - ord[i];
break;
}
ord[i] = id;
path.push_back(i);
i = (i + cnt[i]) % n;
}
int beg = (int)path.size() - loop;
while(q --) {
int k; cin >> k;
k --;
if(k < beg) cout << cnt[path[k]] << endl;
else {
k = (k - beg) % loop;
cout << cnt[path[k + beg]] << endl;
}
}
}
signed main()
{
ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//int T;cin>>T;
//while(T--)
solve();
return 0;
}