数字诗意
题目描述:如果一个数能够以若干个(至少两个)连续的正整数相加表示,那么它就蕴含诗意。例如,数字 6 就蕴含诗意,因为 它可以表示为 1+2+3。而 8 则缺乏诗意,因为它无法用连续的正整数相加表示。
#include <bits/stdc++.h>
using namespace std;
int main()
{
long long n, a, t, cnt = 0;
for (scanf("%lld", &n); n; n--)
{
scanf("%lld", &a);
t = log2(a);
if (pow(2, t) == a)
cnt++;
}
printf("%lld\n", cnt);
return 0;
}首先考虑等差数列求和,这里是题目是公差为一的等差数列,设第一个数是 n,最后一个是 m,我们能列出公式:ai = (n+m)×(m−n+1)/2。移项后得:
2*ai = (m + n)×(m+1− n)
当且仅当 n=m,只能被自身表示。
我们容易发现,n+m 和 m−n+1 奇偶性不同,所以若能写成这种形式,一定是能分解成一个奇数乘一个偶数的形式,所以只要左边是 2n 的形式,就一定不能被表示,否则一定能被表示。
如果数学能力无法达到上述的分析水平,可以简单分析:
n = (a+0) + (a+1) + (a+2) … + (a+(k-1))
= (a+a+a…+a) + (0+1+2+….+(k-1))
= ka + k(k-1)/2
所以:
2n = 2ka + k(k-1)
a = (2n – k(k-1))/(2k)
下一步求k的范围k>=2是题目要求
k的上限。假设1+2+3+…+k = n
k(k+1)/2 = n
k^2 + k = 2n
k<=sqrt(2n)
所有k的范围在[2,sqrt(2n)]
在这个范围内看a有没有整数解即可。
这种解法只能的30%的分数。代码如下:
#include <bits/stdc++.h>
using namespace std;
bool fenjie(long long a);
int main()
{
long long n, a, t, cnt = 0;
for (scanf("%lld", &n); n; n--)
{
scanf("%lld", &a);
if (!fenjie(a))
cnt++;
}
printf("%lld\n", cnt);
return 0;
}
inline bool fenjie(long long a)
{
for (long long k = 2; k <= sqrt(2 * a); k++)
{
if ((2 * a - k * (k - 1)) % (2 * k) == 0)
{
return true;
}
}
return false;
}