天天看點

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;
    }
}