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

一言

萤火之光看起来比平常要更耀眼是错觉吗?今宵会成为永夜的吧。

原文地址:https://www.cnblogs.com/wxyww/p/10094696.html