1. 程式人生 > >[luogu5077][Tweetuzki 愛等差數列]

[luogu5077][Tweetuzki 愛等差數列]

題目連結

思路

數學題

首先列出等差數列求和的式子。

\[S = \frac{(n + m)(n - m + 1)}{2}(n為末項,m為首項)\]

\[S * 2= (n + m)(n - m + 1)\]

若想讓m更小,那麼肯定要讓等差數列中數字的數目更多。也就是讓\((n - m + 1)\)更大,而\((n - m + 1)\)肯定是\(S * 2\)的因子。所以列舉一下\((n - m + 1)\)

假設\((n - m + 1) = x\)\(n = x + m - 1\)。然後前面那一項就變成了\(x + m - 1 + m\)也就是\(2 * m - 1 + x\)

然後前一項也可以通過\(\frac{S * 2}{x}\)得到。這樣就可以得到\[2 * m - 1 + x = \frac{S * 2}{x}\]\[m = \frac{S * 2 - x + 1}{2}\],只要保證,m是正整數就行了。

複雜度就是列舉S * 2的因子x的複雜度。因為後面的都可以用最後這個式子進行O(1)計算。

程式碼

/*
* @Author: wxyww
* @Date:   2018-12-10 08:36:41
* @Last Modified time: 2018-12-10 08:40:48
*/
#include<cstdio>
#include<iostream>
#include<cstdlib>
#include<cmath>
#include<ctime>
#include<bitset>
using namespace std;
typedef long long ll;

ll read() {
    ll x=0,f=1;char c=getchar();
    while(c<'0'||c>'9') {
        if(c=='-') f=-1;
        c=getchar();
    }
    while(c>='0'&&c<='9') {
        x=x*10+c-'0';
        c=getchar();
    }
    return x*f;
}

int main() {
    ll s = read() * 2;
    for(ll x = sqrt(s);x >= 1;--x) {
        if(s % x) continue;
        ll m = (s / x + 1 - x);
        if(m & 1) continue;
        cout<<m / 2 <<" "<< m / 2 - 1 + x;
        return 0;
    }
    return 0;
}

一言

螢火之光看起來比平常要更耀眼是錯覺嗎?今宵會成為永夜的吧。