第一次写博客诶,好高兴!!!
反向操作
题目大意:
在一个首尾相接的正整数数列中,做一次操作的意思是说将每个数变成这
个数和相邻两个数的和,现在给出操作后的数列,请求出初始时的序列。
输入:
第一行一个数N表示序列的长度
下面N行每行一个数表示这个操作后的序列
输出:
输出N行每行一个数,表示操作前的序列
样例输入:
3
5
5
5
样例输出:
2
1
2
(当然也有其他的解,请读者自己判断。。。)
数据范围
N<=10000,输入中的所有数都满足<=109
看到这个题,突然发现好像可以写暴力啊!!!!!
然后看看数据范围。。。。。。
其实这个题是一个数列题(对OIER来说应该没有问题)
应分三种情况考虑,一个是N%3 == 0时,一个是N%3 == 1时,一个是N%3 == 2时
。
反正只要求出一组解,我们就可以用特殊的XX技巧
(a[i]为ans[i-1]+ans[i]+ans[i+1]的和,ans为要输出的答案)
首先,在N%3 == 1时,我们可以把1~N的编号分为{{1},{2~4},{5~7},……
{N-2~N}},然后可以把分好的这个序列分为1和其他数,因为N%3 == 1,所以就可
以理所当然可以算出其他数ans[2]到ans[n]的和,然后我们可以设sum为sum=(a
[1]+a[2]……+a[n])/3,这就是p=ans[1]+ans[2]……+ans[n]的值,然后我
们将p-sum就求出了a[1]的值。然后我们用类似的方法可以求出a[2],得到a[1]和
a[2]的值,就可以求出数列的值。
在N%3 == 2的时候与N%3 == 1的时候类似。
最复杂的莫过于N%3 == 0的时候了。这样也可以先假设ans[1]=0,然后可以一次
求出ans[4],ans[7]……ans[3i+1]的所有值。假如求出的值出现了负数,找出
最小值Min,把每个数加上Min+1,以此保证每个数都大于0。然后也可以用类似的
方法可以设ans[2]=0求出ans[5],ans[8]……ans[3i+2],然后和3i+1的情况一
样,去处理。最后得出a[3i+1]与a[3i+2]自然可以得出a[3i]。
好吧,这个题这样就做完了。
下面放上代码
#include <cstdio>
#include <algorithm>
#define MAXN 10005
using namespace std;
long long ans[MAXN] = {0}, a[MAXN] = {0};
long long sum = 0;
int main()
{
int n;
scanf("%d", &n);
for (int i = 1; i <= n; ++i)
{
scanf("%I64d", &a[i]);
sum = sum + a[i];
}
sum = sum / 3;
if (n == 1)
ans[1] = 1;
else
if (n == 2)
ans[1] = 1, ans[2] = a[1] - 1;
else
if (n == 3)
ans[1] = 1, ans[2] = 1, ans[3] = a[1] - 2;
else
if (n % 3 == 1)
{
long long ss = 0;
for(int i = 2;i <= n; i = i + 3)
ss = ss + a[i];
ans[n] = sum - ss;
ss=0;
for (int i = 3;i <= n; i = i + 3)
ss = ss + a[i];
ans[1] = sum - ss;
ans[2] = a[1] - ans[n] - ans[1];
for (int i = 3; i < n; ++i)
ans[i] = a[i - 1] - ans[i - 1] - ans[i - 2];
}
else
if (n % 3 == 2)
{
long long ss = 0;
for(int i = 2;i <= n; i = i + 3)
ss = ss + a[i];
ans[1] = ss - sum;
ss = 0;
for (int i = 1; i < n; i = i + 3)
ss = ss + a[i];
ans[n] = ss - sum;
ans[2] = a[1] - ans[n] - ans[1];
for (int i = 3; i < n; ++i)
ans[i] = a[i - 1] - ans[i - 1] - ans[i - 2];
}
else
{
long long Min = 0;
for (int i = 4; i <= n; i = i + 3)
{
ans[i] = ans[i - 3] + a[i - 1] - a[i - 2];
Min = min(Min, ans[i]);
}
for (int i = 1; i <= n; i = i + 3)
ans[i] = ans[i] - Min + 1;
Min = 0;
for (int i = 5; i <= n; i = i + 3)
{
ans[i] = ans[i - 3] + a[i - 1] - a[i - 2];
Min = min(Min, ans[i]);
}
for (int i = 2; i <= n; i = i + 3)
ans[i] = ans[i] - Min + 1;
for (int i = 3; i <= n; i = i + 3)
ans[i] = a[i - 1] - ans[i - 1] - ans[i - 2];
}
for (int i = 1; i <= n; ++i)
printf("%I64d\n" ,ans[i]);
return 0;
}
谢谢大家!!!