[luogu5077][Tweetuzki 愛等差數列]
阿新 • • 發佈:2018-12-10
題目連結
思路
數學題
首先列出等差數列求和的式子。
\[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; }