题目:
LL is a ACMER.
One day he find that the number 2 can be expressed as 1-2+3,which can also be expressed as 1+2+3-4 and so on. The number 5 can be expressed as 1-2-3+4+5, which can also be expressed as 1+2+3+4-5, -1+2+3-4+5, 1+2-3+4-5+6 and etc.
So LL thinks that any number N can be achieved by the 1,2,3…, the sequence which starting from 1. To simplify the express, LL wants to find the minimum length of the expression. For example, 2=1-2+3, 5=1-2-3+4+5, 5=1+2+3+4-5, 5=-1+2+3-4+5 can be regarded as the shortest expression.
题意:
给出n,取1—x的连续自然数,填上+/-使得和为n,x最小取多少?
题解:
1—m最大可得到的和为m*(m+1)/2,由m*(m+1)/2>n得到m的最小取值,开始进行验证。
因为m*(m+1)/2>n,故至少有一个数要为负数(设该数为x),此时和比m*(m+1)/2少2倍x
令t=m*(m+1)/2
(t-n)%2=0,则令数(t-n)/2为负;
(t-n)%2=1,则t加上m+1,m+2……直至(t-n)为偶数,令(t-n)/2为负数即可。
若(t-n)/2>当前最大自然数,将(t-n)/2拆分为两个数:
((t-n)/2 )% 2=1 则拆分为(t-n)/2 ,(t-n)/2 +1;
((t-n)/2 )% 2=0 则拆分为(t-n)/2 -2,(t-n)/2 +2;
AC代码:
#include<stdio.h>
#include<string.h>
int n,m,sum[50];
bool f[50];
int main()
{
sum[0]=0;
for (int i=1;i<50;i++) sum[i]=sum[i-1]+i;
while (scanf("%d",&n)!=EOF)
{
memset(f,0,sizeof(f));
for (int i=1;i<50;i++)
if (sum[i]>=n)
{
m=i;
break;
}
int t=sum[m]-n;
if (t % 2==0) f[t/2]=true;
else
{
while (t % 2) m++,t+=m;
int k=t/2;
if (k>m)
{
if (k % 2)
f[k/2+1]=f[k/2-1]=true;
else
f[k/2-2]=f[k/2+2]=true;
}
else
f[k]=true;
}
for (int i=1;i<=m;i++)
{
if (f[i]) printf("-"); else printf("+");
printf("%d",i);
}
printf("\n");
}
return 0;
}