天天看点

Codeforces Round #645 (Div. 2) C. Celex Update (思维,数学推理)

题目链接

题意:

给你一个如下规律的方阵

Codeforces Round #645 (Div. 2) C. Celex Update (思维,数学推理)

依次按斜率为1的斜线上放置数字。1的位置坐标为(1,1),现在问,给定你起点坐标和终点坐标且你每次只能向右或者向下走,问有多少种方法能从起点到终点,且每一种方法的路径和都不同。

思路:

Codeforces Round #645 (Div. 2) C. Celex Update (思维,数学推理)

举个例子好解释点

如图所画的小矩形中,我们可以先求出最大和和最小和,我们又经过观察,发现最大和和最小和之间的数都是连续的。

那么我们只要求出最大和和最小和就可以了,但是由于终点和起点都是随机给,且数的规律很难算,所以要准确的算出最大和是多少和最小和是多少是很困难的。

但是如果我们把他拆开来呢?

最大和: 1 3 6 9 13 18 24 的所有数相加

最小和: 1 2 4 7 11 17 24 的所有数相加

每一步数的差: 0 1 2 2 2 1 0

那么每一步差的和即为最大值和最小值的差,也为答案

这样拆开来算,假设画线中矩形的长为x,宽为y,由于现在我们只能向下走和向右走,可以算出我们从起点到终点一定要x+y-2步,为了后面的方便我们现在把长和宽都看做减1,那么我们现在需要x+y步(图中长为4,宽为2)

现在每一步的差为:0 1 … x x x … x-1 x-2 … 1 0

我们又把他分开成俩部分

一部分 (0 1 … x-2 x-1) ( x-1 x-2 … 1 0),由等差数列求和公式得和为x*(x-1)

另外一部分为x x x x…有多少个x呢?前面我们算了要走x+y步,但是有x+y+1个数,因为起点有一个数而现在我们知道第一部分走了2*x个数,那么第二部分就还有y-x+1个数

那么答案出来了:第一步与第二部的和为

x*(x-1) + (y-x+1)*x 简化后为x * y + 1(这里的x,y是指矩形的长和宽都减1)。

代码到不难,就是推理过程要麻烦点

AC代码

#include <bits/stdc++.h>
inline int read(){char c = getchar();int x = 0,s = 1;
while(c < '0' || c > '9') {if(c == '-') s = -1;c = getchar();}
while(c >= '0' && c <= '9') {x = x*10 + c -'0';c = getchar();}
return x*s;}
using namespace std;
#define NewNode (TreeNode *)malloc(sizeof(TreeNode))
#define Mem(a,b) memset(a,b,sizeof(a))
const int N = 1e8 + 5;
const long long INFINF = 0x7f7f7f7f7f7f7f;
const int INF = 0x3f3f3f3f;
const double EPS = 1e-7;
const unsigned long long mod = 998244353;
const double II = acos(-1);
const double PP = (II*1.0)/(180.00);
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pii;
typedef pair<ll,ll> piil;
int main()
{
    std::ios::sync_with_stdio(false);
    cin.tie(0),cout.tie(0);
    int t;
    cin >> t;
    while(t--)
    {
        int x1,y1,x2,y2;
        cin >> x1 >> y1 >> x2 >> y2;
        ll num1 = x2-x1,num2 = y2-y1;//长和宽都减1的结果
        cout << num1*num2+1 << endl;
    }
}