Problem - A - Codeforces翻译:
您将得到一个由𝑛个整数组成的数组𝑎。
你想要让𝑎的所有元素都等于零,只需执行以下操作三次:
选择一个段,对于这个段中的每一个数字,我们可以给它加上𝑙𝑒𝑛的倍数,其中𝑙𝑒𝑛是这个段的长度(添加的整数可以不同)。
可以证明,总是有可能使𝑎的所有元素等于零。
输入
第一行包含一个整数𝑛(1≤𝑛≤100000):数组的元素个数。
第二行包含数组𝑎中的𝑛元素,以空格分隔:𝑎1,𝑎2,…,𝑎𝑛(−109≤𝑎𝑖≤109)。
输出
输出应该包含代表三个操作的六行。
对于每个操作,打印两行:
第一行包含两个整数𝑙,𝑟(1≤𝑙≤𝑟≤𝑛):所选段的边界。
第二行包含𝑟−𝑙+ 1整数𝑏𝑙,𝑏𝑙+ 1,…,𝑏𝑟(1018−≤𝑏𝑖≤1018):数字添加到𝑎𝑙,𝑎𝑙+ 1,…,𝑎𝑟,分别;𝑏𝑖必须能被𝑟−𝑙+1整除。
例子
inputCopy
4
1 3 2 4
outputCopy
1
-1
3 4
4个2
2 4
-3 -6 -6
思路:
每次操作在区间里面的每个值加上区间长度的任意倍数,操作三次后可以所有元素为0。必须操作三次,固定操作次数,这就比较有趣了。固定操作次数,一定可以达成,我们直接从性质规律入手就好了。每次改变的值是区间长度,我们可以将操作分开,最后一次将元素清零,前两次将数组所有元素变成n的倍数,这很容易做到,我们将n个数分成 1,2~n,区间长度分别是,1,n-1,1的话可以随便加,2~n的数,只要加上本身的n-1倍就好了,很容易证明,x+(n-1)*x=n*x。
所以我们可以直接写代码,当然,我们这样写,1需要特判掉。
代码:
/*Looking! The blitz loop this planet to search way
Only my RAILGUN can shoot it 今すぐ
身体中を 光の速さで
駆け巡った確かな予感
掴め! 望むものなら残さず
輝ける自分らしさで
信じてるよ あの日の誓いを
この瞳に光る涙それさえも 強さになるから
*/
#include <iostream>
#include <algorithm>
#include <string.h>
#include <string>
#include <math.h>
#include <stdio.h>
#include<vector>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<tuple>
#include<numeric>
using namespace::std;
typedef long long ll;
inline __int128 read(){
__int128 x = 0, f = 1;
char ch = getchar();
while(ch < '0' || ch > '9'){
if(ch == '-')
f = -1;
ch = getchar();
}
while(ch >= '0' && ch <= '9'){
x = x * 10 + ch - '0';
ch = getchar();
}
return x * f;
}
inline void print(__int128 x){
if(x < 0){
putchar('-');
x = -x;
}
if(x > 9)
print(x / 10);
putchar(x % 10 + '0');
}
int n;
ll a[100005];
int main(){
ios::sync_with_stdio(false);
cin.tie(); cout.tie();
cin>>n;
for (int i =1; i<=n; i++) {
cin>>a[i];
}
if (n==1) {
printf("1 1\n");
printf("%lld\n",a[1]);
printf("1 1\n");
printf("%lld\n",a[1]);
printf("1 1\n");
printf("%lld\n",-3*a[1]);
return 0;
}
printf("1 1\n");
printf("%lld\n",a[1]*(n-1));
printf("2 %d\n",n);
for (int i=2; i<=n; i++) {
printf("%lld ",a[i]*(n-1));
}printf("\n");
printf("1 %d\n",n);
for (int i=1; i<=n; i++) {
printf("%lld ",-a[i]*n);
}printf("\n");
return 0;
}