一個數組被稱爲完美的,當且僅當其中存在一個元素,它的值是除了它之外剩下的所有元素的和。
蒜頭君現在獲得了一個數組。他想去掉數組中的一個元素,使得這個數組變成完美的。
他想知道這個數組有幾種方案可以變成完美的。當去掉的元素在原數組中的位置不同時,即爲不同的方案。
輸入格式:
輸入的第一行包含一個整數n(2<=n<=200000).
輸入的第二行包括n個整數,爲蒜頭君獲得的數組裏面的每個元素ai(2<=ai<=1000000)
輸出格式:
輸出有兩行。
第一行是方案的個數 k。第二行有 k個用單個空格分開的整數,分別表示去掉的元素在原數組中的位置(按照輸入的順序)。
說明:如果沒有方案,輸出一個 0 即可。
示例1:
輸入
5
2 5 1 2 2
輸出:
3
1 4 5
示例2:
輸入:
4
8 3 5 2
輸出:
2
1 4
方法一:這個方法是最容易理解的,但是不夠優化,運行時間過長
`#include<iostream>
#include<cstring>
using namespace std;
int main()
{
int n;
cin>>n;
int a[200000],b[200000];
int k=0,i,j;
int sum=0;
for( i=0;i<n;i++)
{
cin>>a[i];
sum+=a[i];//將所有數相加
}
for( i=0;i<n;i++)//這裏a[i]是去掉的數
{
for(j=0;j<n;j++)
{
if(2*a[j]==(sum-a[i]))//如果一個數的二倍等於剩下數的和,則是完美的
{
b[k++]=i+1;//這裏是i+1,因爲要的是位置
break;
}
}
}
cout<<k<<endl;
for(i=0;i<k;i++)
cout<<b[i]<<" ";
return 0;
}
`
方法二:這一種方法對於上一個來說已經優化了些,因爲是完美數組,則剩下數的和一定是等於這個數組中最大的那個數,所以只要判斷最大的數是不是等於剩下數的和就可以。
但這個要判斷去掉的這個數是不是最大值。這個是重點。
#include<iostream>
using namespace std;
int main()
{
int n,sum=0,a[200000],b[200000];
cin>>n;
int i,j,k=0;
int sum2;
int max=0;
for(i=0;i<n;i++)
{
cin>>a[i];
sum+=a[i];
if(a[i]>max) max=a[i]; //記錄最大值
}
for(i=0;i<n;i++)
{
sum2=sum-a[i];//a[i]是刪去的數
//如果去掉的不是最大值
if(a[i]!=max)
{
if(2*max==sum2)
{
b[k++]=i+1;
}
continue;//**如果去掉的數不是最大值,就執行這條語句,跳出本次循環,就不會再執行下面的語句了,接着再判斷下面一個去掉的數是不是最大值**
}
//如果去掉的是最大值
for(j=0;j<n;j++)
{
if(j==i) continue;//如果j==i則這次循環不執行,判斷下一個數
if(2*a[j]==sum2)
{
b[k++]=i+1;
break;
}
}
}
cout<<k<<endl;
for(i=0;i<k;i++)
cout<<b[i]<<' ';
return 0;
}
方法三:這個可以算是最優的一個方法了,我也就只想到着了。
這個思路是,因爲剩下的數的和是等於數組中最大值,所以把最大的數去掉後,就該考慮次大值了,這個次大值可以等於最大值,就是說這個數組中可以有相同的數,且這相同的數是最大的數。
#include<iostream>
using namespace std;
int main()
{
int n,sum=0,a[200000],b[200000];
cin>>n;
int i,j,k=0;
int sum2;
int max1=0,max2=0;//max1>=max2
for(i=0;i<n;i++)
{
cin>>a[i];
sum+=a[i];
if(a[i]>max1)
{
max2=max1;
max1=a[i];
}
else if(a[i]>max2)//存在一些數小於max1,但大於max2
{
max2=a[i];
}
}//最大值次大值都找到
for(i=0;i<n;i++)
{
sum2=sum-a[i];//a[i]是刪去的數
//如果去掉的不是最大值,則就用最大值比較
if(a[i]!=max1)
{
if(2*max1==sum2)
{
b[k++]=i+1;
}
}
else//如果去掉的是最大值,則用次大值比較
{
if(2*max2==sum2)
{
b[k++]=i+1;
}
}
}
cout<<k<<endl;
for(i=0;i<k;i++)
cout<<b[i]<<' ';
return 0;
}
或者這樣寫:
#include<iostream>
using namespace std;
int main()
{
int n;
cin>>n;
int a[200000],b[200000];
int k=0,i,j;
int sum=0,Max=0,max=0;//Max爲原數組最大值,max爲除去最大值後的次最大值(可以等於最大值)
int temp; //用於標記原數組最大值的位置i
for( i=0;i<n;i++)
{
cin>>a[i];
sum+=a[i];
if(a[i]>Max) {Max=a[i];temp=i;}
}
for(i=0;i<n;i++)
{
if(a[i]>max&&temp!=i)
{
max=a[i]; //表示次最大值
}
}
double x;
for(i=0;i<n;i++)
{
x=(double)(sum-a[i])/2.0;
if(a[i]!=Max&&x==Max)//除去的數不是最大值
{
b[k++]=i+1;
}
if(a[i]==Max&&x==max)//除去的數是最大值則考慮次最大值
{
b[k++]=i+1;
}
}
cout<<k<<endl;
for(i=0;i<k;i++)
cout<<b[i]<<" ";
return 0;
}