PS:由于打表姿势没对,错过了很好写的一道题。经过打表你发发现最上角的矩阵,如果是奇数,大小为 L * L,如果为偶数,大小为 2L * 2L,是重复出现。为了便于计算,将循环节的大小统一为 2L * 2L,然后预处理二维前缀和,瞎搞搞就出来了。
#pragma warning(disable:4996) #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #include<bitset> #include<vector> #include<queue> #include<map> #include<string> #include<stack> #define ll long long #define P pair<int, int> #define PP pair<int,pair<int, int>> #define pb push_back #define pp pop_back #define lson root << 1 #define INF (int)2e9 + 7 #define rson root << 1 | 1 #define LINF (unsigned long long int)1e18 #define mem(arry, in) memset(arry, in, sizeof(arry)) using namespace std; int n, T; int mp[1005][1005], a[20], dp[100][100]; ll get(int s, int t) {
if (s == -1 || t == -1) return 0;
int x = s % n, cnt_x = s / n; int y = t % n, cnt_y = t / n; return 1ll * dp[x][n - 1] * cnt_y + 1ll * dp[n - 1][y] * cnt_x + 1ll * dp[n - 1][n - 1] * cnt_x * cnt_y + 1ll * dp[x][y]; } int main() { scanf("%d", &T); while (T--) { scanf("%d", &n); for (int i = 0; i < n; ++i) scanf("%d", &a[i]); int cur = 0; for (int i = 0; i <= 100 ; ++i) { for (int j = 0; j <= i; ++j) { mp[j][i - j] = a[cur]; cur = (cur + 1) % n; } } dp[0][0] = mp[0][0]; for (int i = 1; i < 2 * n; ++i) dp[0][i] = dp[0][i - 1] + mp[0][i]; for (int i = 1; i < 2 * n; ++i) dp[i][0] = dp[i - 1][0] + mp[i][0]; for (int i = 1; i < 2 * n; ++i) for (int j = 1; j < 2 * n; ++j) dp[i][j] = mp[i][j] + dp[i][j - 1] + dp[i - 1][j] - dp[i - 1][j - 1]; n = 2 * n; int q, x0, y0, x1, y1; scanf("%d", &q); while (q--) { scanf("%d %d %d %d", &x0, &y0, &x1, &y1); //cout << get(x1, y1) << endl; printf("%lld ", get(x1, y1) - get(x1, y0 - 1) - get(x0 - 1, y1) + get(x0 - 1, y0 - 1)); } } return 0; }