HZNUOJ 2803 two-dimensional prefix and +gcd

Sharpshooter JoneySun (Easy Version)

Time Limit: 1 s Memory Limit: 256 MB
Submission:146 AC:32 Score:100.00

Description
Easy Version and a little bit hard Version only differ in data range

JoneySun was trapped in a prison divided by 1×1 grid by the evil wifepie. The evil wifepie watched JoneySun’s jokes somewhere in the prison. Fortunately, JoneySun had a gun in his hand. Unfortunately It is wifepie who has mastered the doppelganger technique.

We think that this prison is a 2n×2m grid. JoneySun is trapped in the middle. Except for JoneySun, there is a wifepie avatar at the other intersections of the grid. The range of JoneySun's gun is infinite. If the bullet hits the clone, the clone will disappear and the bullet will continue to travel in a straight line. If the bullet hits the wifepie body, the wifepie will be destroyed by JoneySun. JoneySun wanted to know the maximum number of bullets needed to destroy a wifepie.


An integer T in the first line of Input (1≤T≤100) indicates that there are T groups of inputs

Two integers n, m (1≤n,m≤103) in the second line, see the title for the meaning

Samples
input
1
1 1
output
8
Hint

As shown in the figure, the red dot indicates the location of JoneySun, and the blue dot indicates the clone of wifepie. It takes up to 8 bullets to destroy all clones of wifipie.

Please pay attention to the complexity, T is very large, please try all the metaphysical optimizations you can think of

Problem solution: The meaning of the problem is to find out how many non-overlapping rays from the source point to each vertex, that is, to find whether gcd(i,j) is equal to 1, or gcd(i,j)=d,gcd Whether (i/d, j/d) is equal to 1, if it is equal to 1, it means that it is a feasible side. Because every rectangle is symmetric, it can be transformed into a quadrant problem to solve. Because the problem has 100 sets of test data, the complexity is relatively large, so the violent solution will be T, so we consider using a two-dimensional prefix and preprocessing, and then O(1) for query.
The AC code is as follows:

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<cctype>
#include<iomanip>
#include<map>
#include<vector>
#include<list>
#include<deque>
#include<stack>
#include<queue>
#include<set>
#include<cctype>
#include<string>
#include<stdexcept>
#include<fstream>
#include<sstream>
#define mem(a,b) memset(a,b,sizeof(a))
#define mod 10000007
#define debug() puts("what the fuck!")
#define dedebug() puts("what the fuck!!!")
#define ll long long
#define ull unsigned long long
#define speed {
    
    ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); };
using namespace std;
const double PI = acos(-1.0);
const int maxn = 1e6 + 50;
const int N = 35;
const int INF = 0x3f3f3f3f;
const int inf = 0xfffffff;//比INF小,防止累加爆int
const double esp_0 = 1e-6;
const double gold = (1 + sqrt(5)) / 2;
int gcd(int x, int y) {
    
    
	return y ? gcd(y, x % y) : x;
}
int n, m;
int dp[1020][1020];
int main() {
    
    
	mem(dp, 0);
	for (int i = 1; i <= 1010; ++i) {
    
    
		for (int j = 1; j <= 1010; ++j) {
    
    
			int step = gcd(i, j);
			if (step == 1)dp[i][j] = dp[i - 1][j] + dp[i][j - 1] - dp[i - 1][j - 1] + step;//如果是可行边,则加上改点的值
			else {
    
    
				dp[i][j] = dp[i - 1][j] + dp[i][j - 1] - dp[i - 1][j - 1];//如果不是可行边,则不加
			}
		}
	}
	int t;
	scanf("%d", &t);
	while (t--) {
    
    
		scanf("%d%d", &n, &m);
		int ans = dp[n][m] * 4 + 4;
		printf("%d\n", ans);
	}
	return 0;
}

Guess you like

Origin blog.csdn.net/qq_40924271/article/details/107872288