タイトル:4列
そのイタリア:ZJMは、4つの列A、B、C、Dを有し、各列は桁数Nを有します。ZJMそれぞれの列番号から取られた数が、彼はそのような4と0の数、そのプログラムのどのように多くの種類を知っていただきたいと思います。
場合は、列の数が異なる数として扱うために、数字の同じ複数有しています。
彼を助けてください!
入力:
nは(数は列の桁数を表す。)(1≤n≤4000):最初の行
4つの数字の次のn行目、第i行、列A、B、C、Dの各数i番目の桁(ない以上28以下の電力に数字2)
出力:
異なる組み合わせの数の出力。
例:
問題解決のアイデア:まず、暴力、O(N4)直接の暴力、その後、タイムアウト(手動面白い)について考えます。次いで、最適化、我々ができ、第1のA、B、及び計算され、アレイにソート次いで終わっ、時間複雑であるようにO(N2 logn2)。次いで、2分、続いてC + Dを、模索O(N2 logn2)、A + Bの位置のC + Dの反対を見つけることであり、さらにその結果、N2のような使用の半分の時間の複雑*のLOGNがある場合、それが許容可能です。
コード:
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
int a[4][4005];
vector<int> h,z;
int main()
{
int n,x;
cin>>n;
for(int i=0;i<n;i++)
{
for(int j=0;j<4;j++)
{
cin>>x;
a[j][i]=x;
}
}
for(int i=0;i<n;i++)
{
for(int j=0;j<n;j++)
{
h.push_back(a[0][i]+a[1][j]);
}
}
sort(h.begin(),h.end());//A+B排序
for(int i=0;i<n;i++)
{
for(int j=0;j<n;j++)
{
z.push_back(a[2][i]+a[3][j]);
}
}//C+D不用排序
int total=0;
for(int i=0;i<z.size();i++)
{
z[i]=-z[i];
int l=0,r=h.size()-1;
int ans=-1;
while(l<=r)//找相反数二分
{
int mid=(l+r)/2;
if(h[mid]>z[i])
{
r=mid-1;
}else if(h[mid]<z[i])
{
l=mid+1;
}else if(h[mid]==z[i])
{
ans=mid;
l=mid+1;
}
}
if(ans==-1)//没找到,白给
{
continue;
}
if(h[ans]==z[i])
{
total++;//找到
for(int j=ans-1;j>=0;j--)//在这个数周围找找看有没有相同的
{
if(h[j]==z[i])
{
total++;
}else
{
break;
}
}
for(int j=ans+1;j<h.size();j++)
{
if(h[j]==z[i])
{
total++;
}else
{
break;
}
}
}
}
cout<<total<<endl;
}