1. 程式人生 > >【JZOJ A組】小凱學數學

【JZOJ A組】小凱學數學

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

思路

區間DP
設f[i][j][0…7]為區間i…j能否合成0…7

於是列舉斷點,再列舉轉移點即可

程式碼

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int inf=0x3f3f3f3f;
int s=0,ss=inf,n;
int f[157][157][8];
int main()
{
	freopen("math.in","r",stdin); freopen("math.out","w",stdout);
	scanf("%d",&n);
	for(int i=1; i<=n; i++)
	{
		int x;
		scanf("%d",&x); f[i][i][x]=1; s=max(x,s); ss=min(ss,x);
	}
	for(int i=2; i<=n; i++) for(int j=1; j<=n-i+1; j++)
	{
		int l=j,r=j+i-1;
		for(int k=j; k<=j+i-1; k++)
		{
			for(int x=ss; x<=s; x++) for(int y=x; y<=s; y++)
			{
				f[l][r][(x+y)>>1]|=(f[l][k][x]&f[k+1][r][y])|(f[k+1][r][x]&f[l][k][y]);
			}
		}
	}
	for(int i=ss; i<=s; i++) if(f[1][n][i]) printf("%d ",i);
}