jzoj5935小凱學數學
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][k] 代表 i 到 j 的區間是否可能結果爲 k
於是就很顯然了
動態轉移方程:f[i][j][k] = f [i][l][p] | f[r][j][q]
代碼:
#include<cstdio>
#include<cstring>
#define maxx(a,b) a>b?a:b
#define minn(a,b) a<b?a:b
const int mx=150;
int n,ma=0,mi=999999999,x;
bool f[mx+5][mx+5][10];
int main(){
freopen("math.in","r",stdin);
freopen("math.out","w",stdout);
memset(f,0,sizeof(f));
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d",&x),f[i][i][x]=1;
ma=maxx(ma,x),mi=minn(mi,x);
}
for(int i=2;i<=n;i++)
for(int j=1;j<=n-i+1;j++){
int l=j,r=i+j-1;
for(int k=j;k<=i+j-1;k++)
for(int x=mi;x<=ma;x++)
for(int y=x;y<=ma;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=mi;i<=ma;i++)
if(f[1][n][i])printf("%d ",i);
return 0;
}