对于b大于 sqrt(n)的,暴力处理的话,那么算出每个的复杂度是sqrt(n),就是把n分成了sqrt(n)段,
其他的,b小于sqrt(n)的,那么就最多只有sqrt(n)个,考虑到,如果b相同的话,放在一起,能不能记录一个结果呢?
用dp[pos]表示从pos这个位置开始,间隔为b的答案值。
那么需要从后面往前dp,每次转移dp[i] = dp[i + b] + a[i]即可
#include <cstdio> #include <cstdlib> #include <cstring> #include <cmath> #include <algorithm> using namespace std; #define inf (0x3f3f3f3f) typedef long long int LL; #include <iostream> #include <sstream> #include <vector> #include <set> #include <map> #include <queue> #include <string> int magic; int n; const int maxn = 3e5 + 20; int a[maxn]; struct node { int a, b; int id; bool operator < (const struct node &rhs) const { return b < rhs.b; } }query[maxn]; LL ans[maxn]; LL dp[maxn]; void work() { scanf("%d", &n); magic = (int)sqrt(n * 1.0); for (int i = 1; i <= n; ++i) { scanf("%d", &a[i]); } int q; scanf("%d", &q); for (int i = 1; i <= q; ++i) { scanf("%d%d", &query[i].a, &query[i].b); query[i].id = i; } sort(query + 1, query + 1 + q); int last = -1; for (int i = 1; i <= q; ++i) { if (query[i].b >= magic) { for (int j = query[i].a; j <= n; j += query[i].b) { ans[query[i].id] += a[j]; } } else { if (query[i].b == last) { ans[query[i].id] = dp[query[i].a]; } else { // cout << query[i].a << " " << query[i].b << endl; last = query[i].b; for (int j = n; j >= 1; --j) { if (j + query[i].b > n) { dp[j] = a[j]; } else { dp[j] = dp[j + query[i].b] + a[j]; } } ans[query[i].id] = dp[query[i].a]; } } } // for (int i = 1; i <= n; ++i) { // printf("%I64d ", dp[i]); // } // cout << endl; for (int i = 1; i <= q; ++i) { printf("%I64d\n", ans[i]); } return; } int main() { #ifdef local freopen("data.txt","r",stdin); #endif work(); return 0; }
时间: 2024-10-03 23:53:09