JZOJ5935. 【NOIP2018模擬10.29】小凱學數學
阿新 • • 發佈:2018-11-03
Description
由於小凱上次在找零問題上的疑惑,給大家在考場上帶來了很大的麻煩,他決心好好學習數學
本次他挑選了位運算專題進行研究 他發明了一種叫做“小凱運算”的運算子:
a$b =( (a&b) + (a|b) )>>1
他為了練習,寫了n個數在黑板上(記為a[i]) 並對任意相鄰兩個數進行“小凱運算”,把兩數擦去,把結果留下 這樣操作n-1次之後就只剩了1個數,求這個數可能是什麼?
將答案從小到大順序輸出
Input
4
1 4 3 2
Output
1 2
Sample Input
4
1 4 3 2
Sample Output
1 2
Data Constraint
30% n<=10 0<=a[i]<=7
70% n<=150 0<=a[i]<=3
100% n<=150 0<=a[i]<=7
題解
先分析一下題目給出的運算,
a $ b =( (a&b) + (a|b) )>>1
觀察二進位制位置上面,就是一個交集再加上一個並集,其實就是a+b嘛,
所以呢,這個東西就是(a+b)/2 。
知道了這個性質,出來起來就比較方便了,
設
表示從i到j這一段,是否最終是否可以變為一個數k,
轉移就先列舉一個區間[i,j],然後列舉一個分界點,將一個區間分成兩個區間,
最後再列舉這兩個區間最終是什麼數字。
code
#include <cstdio>
#include <iostream>
#include <cstring>
#define N 153
#define P putchar
#define G getchar
using namespace std;
char ch;
void read(int &n)
{
n=0;
ch=G();
while((ch<'0' || ch>'9') && ch!='-')ch=G();
int w=1;
if(ch=='-')w=-1,ch=G();
while('0'<=ch && ch<='9')n=(n<<3)+(n<<1)+ch-'0',ch=G();
n*=w;
}
int n,x;
bool f[8][N][N];
int main()
{
freopen("math.in","r",stdin);
freopen("math.out","w",stdout);
memset(f,0,sizeof(f));
read(n);
for(int i=1;i<=n;i++)read(x),f[x][i][i]=1;
for(int l=2;l<=n;l++)
for(int i=1;i+l-1<=n;i++)
for(int j=i+1;j<=n;j++)
for(int p1=0;p1<8;p1++)
for(int p2=0;p2<8;p2++)
f[(p1+p2)>>1][i][l+i-1]|=f[p1][i][j-1]&&f[p2][j][i+l-1];
for(int i=0;i<8;i++)
if(f[i][1][n])P(i+48),P(' ');
return 0;
}