1. 程式人生 > 其它 >三元組加強版

三元組加強版

Problem

題目描述

給定兩個整數 \(n,m\) 問有多少三元組 \((x,y,z)\) 滿足:

  • \(0\le x,y,z\le n\)
  • \(x+y+z=m\)

輸入格式

一行給出兩個整數 \(n,m\)

輸出格式

一個整數,代表答案。

Example&Prompt

輸入輸出樣例

樣例\(1\)
輸入:$2\ 2\ \ \ $ 輸出:\(6\)
樣例\(2\)
輸入:$3\ 15\ $ 輸出:\(1\)

資料範圍

對於\(20\%\)的資料,滿足\(1\le n\le 100\)
對於\(50\%\)的資料,滿足\(1\le n\le 10^4\)
對於\(100\%\)的資料,滿足\(1\le n\le 10^7,0\le m\le3n\)

Solution1(20pts)

暴力列舉\(x,y,z\),再判斷合不合法,時間複雜度為\(O(n^3)\)

Solution2(50pts)

暴力列舉\(x,y\),根據條件\(2\)算出\(z\),再判斷合不合法,時間複雜度為\(O(n^2)\)

Solution3(100pts)

暴力列舉\(x\),再求出\(y,z\)的所有可能性。

那如何求\(y,z\)的所有可能性呢?不妨先令\(k=m-x\),因為條件\(1\),所以當\(k< 0\)時沒有合法的解,只要討論\(k\ge 0\)的情況。

首先先看一種簡單的情況:\(n\ge k\)

根據條件\(2\),我們有\(y+z=k\)

,因為\(n\ge k\),所以不存在不合法的結果。

因此,我們就是要求兩個自然數之和為\(k\)的數量,這個很明顯是\(k+1\)種,舉個例子:

\[4=0+4=1+3=2+2=3+1=4+0 \]

其實也就是\(k=i+(k-i)(0\le i\le k)\),共\(k+1\)種可能。

然後再看\(n<k\)的情況,我們依舊有\(y+z=k\),但此時可能有不合法結果,甚至沒有合法結果。

我們先設\(y=n\),此時\(z=k-n=m-2n\)為最小值,如果\(z>n\),那麼代表沒有合法結果,因為最小的可能也不符合要求,也就沒有符合要求的結果了。

然後考慮有不合法結果也有合法結果,根據上面的例子\(4\)

我們可以看出,分解的兩端(即\(y,z\)分別取較大值時)最可能不符合要求,因此我們只要找出有多少不符合要求的值,再用總情況減去,就知道了有多少合法值。

很明顯,從\(k=i+(k-i)(0\le i\le k)\)可以看出\(i>n\)不符合情況的數量是\(k-n\)\(k-i\)不符合情況的數量也是\(k-n\)(正好與\(i\)不符合情況相反)。

總情況仍是\(k+1\),因此,這時候符合情況的數量就是\(k+1-(k-n)* 2=2n-k+1\)

我們把所有情況加起來就是答案了,時間複雜度為\(O(n)\)

Code

#include<bits/stdc++.h>
using namespace std;
int main()
{
    int n,m,ans=0;
    scanf("%d%d",&n,&m);
    for(int i=0;i<=n;i++)
    {
        int k=m-i,j=0;
        if(k>=0)
        {
            if(k>n)
            {
                if(k-n>n)
                j=0;
                else
                j=2*n-k+1;
            }
            else
            j=k+1;
        }
        ans+=j;
    }
    printf("%d",ans);
    return 0;
}