【NOIP2015模擬】終章-劍之魂
阿新 • • 發佈:2018-12-31
背景介紹
古堡,暗鴉,斜陽,和深淵……
等了三年,我獨自一人,終於來到了這裡……
“終焉的試煉嗎?就在這裡嗎?”我自言自語道。
“終焉的試煉啊!就在這裡啊!”我再一次自言自語道。
“這背後可能有那個東西嗎?”我自言自語道。
“這背後一定有那個東西呢!”我又一次自言自語道。
我沉默著,踏上黑漆漆的索橋,小心翼翼地,拿出鋒利的注入我靈魂的雙劍……
“那麼,我們開始吧……”我最後一次自言自語道。
題目描述
My soul of my sowrd!
終焉的試煉即將到來,作為一名有修養的劍士,雖然沒有習得n刀流但是二刀流還是沒問題的。然而我也是個劍的收藏者,家裡屯著n把劍,每一把劍都有一個靈魂值a[i],由於一些劍之間可能有共鳴,所以我需要兩把契合度最高的劍。據劍聖所說,兩把編號為i,j劍的契合度為a[i] and a[j]。如何深得劍的靈魂呢?
注:AND 為按位與運算,先將數轉成二進位制,不滿位數的補全0,然後成為兩個長度相同的二進位制數,處理的時候,兩個相應的二進位制位都為1,該位的結果值才為1,否則為0。例:0101(5) and 0011(3)=0001(1)
輸入
第一行一個整數n,代表藏劍數。
第二行n個整數,第i個整數表示a[i]。
輸出
輸出包含一個正整數,最好的兩把劍的契合度。
思路
我們先測試幾組資料。1.6 and 4=4. 2.6 and 2=2. 3.4 and 2=0.不難發現,兩個數越大,運算出來結果越大。由此得出解法。
解法+時間複雜度
先從大到小快排(n log n),再n^2列舉。WTF!這你都過了?別急,聽完嘛。如果我們and出來的數沒上一次大,後面的數and出來一定沒有這次大,我們就可以break了。所以總時間複雜度為O(n log n+玄(學))
#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
int n,i,u,k,a[1000001],b[1000001][32],xh,h[32][32],j,o[1000001];
long long ans;
bool bz,bj[1000001];
int ks(long long x)
{
if (x==0) return 1;
if (x==1) return 2; else
{
int s=x%2;
if (s==1) return ks(x/2)*ks(x/2)*2;else return ks(x/2)*ks(x/2);
}
}
int main()
{
freopen("sword.in","r",stdin);
freopen("sword.out","w",stdout);
scanf("%d",&n);
for (i=1;i<=n;i++)
{
scanf("%d",&a[i]);
while (a[i]!=0)
{
b[i][0]++;
b[i][b[i][0]]=a[i]%2;
a[i]/=2;
}
xh=max(xh,b[i][0]);
h[b[i][0]][0]++;
h[b[i][0]][h[b[i][0]][0]]=i;
}
bz=0;
for (i=xh;i>=1;i--)
{
if (bz==0)
{
k+=h[i][0];
for (j=1;j<=h[i][0];j++)
{
bj[h[i][j]]=1;
}
}
u=0;
for (j=1;j<=n;j++)
if (b[j][i]==1 && bj[j]==1) u++;else
{
o[0]++;
o[o[0]]=j;
}
if (u>=2)
{
ans+=ks(i-1);
for (j=1;j<=o[0];j++)
bj[o[j]]=0;
bz=1;
}
memset(o,0,sizeof(o));
}
printf("%lld",ans);
}