Official

B - Inverse Prefix Sum Editorial by kyopro_friends


先頭から順に \(A_i\) の要素を求めていくことができます。

解法1

  • \(A_1=S_1\) です。
  • \(S_2=A_1+A_2\) なので、\(A_2=S_2-A_1\) です。
  • \(S_3=A_1+A_2+A_3\) なので、\(A_3=S_3-A_1-A_2\) です。
  • \(\vdots\)

このように、\(A_k=S_k-A_1-\ldots-A_{k-1}\) であり、\(A_k\) を求めようとする時点では \(A_1,\ldots,A_{k-1}\) は既に求めているので、この式を使って \(A_k\) を求めることができます。

実装例(C)

#include<stdio.h>

int main(){
	int n;
	scanf("%d",&n);
	int s[10];
	for(int i=0;i<n;i++)scanf("%d",s+i);

	int a[10];
	for(int i=0;i<n;i++){
		//a[i]を求める
		int temp=s[i];
		for(int j=0;j<i;j++)temp-=a[j];
		a[i]=temp;
	}

	for(int i=0;i<n;i++)printf("%d%c",a[i],i==n-1?'\n':' ');
}

解法2

\(S_i=(A_1+\ldots+A_{i-1})+A_i=S_{i-1}+A_i\) であることから、\(S_i-S_{i-1}=A_i\) となります。この式を使って、\(A_i\) を求めることができます。なお、\(S_0=0\) と定めると、\(i=1\) の場合にもこの式は成り立ちます。添字 \(i-1\) が配列外参照を起こさないように注意して実装しましょう。

実装例(C)

#include<stdio.h>

int main(){
	int n;
	scanf("%d",&n);
	int s[11];
	s[0]=0;
	for(int i=1;i<=n;i++)scanf("%d",s+i);

	int a[10];
	for(int i=0;i<n;i++)a[i]=s[i+1]-s[i];
	
	for(int i=0;i<n;i++)printf("%d%c",a[i],i==n-1?'\n':' ');
}

余談

解法1の計算量は \(O(N^2)\) であるため、もし \(N=200000\) の場合には、実行時間が長くかかります。一方、解法2の計算量は \(O(N)\) であるため、\(N=200000\) の場合にも十分高速に答えを求めることができます。C 問題以降に挑む際には、このように、計算量の違いを意識できるようになっておくと良いでしょう。

posted:
last update: