【NOIPシミュレーション試験]:ビット演算(数学)

トピックポータル(内部タイトル12)


入力形式

最初の行は、3つの整数の$ N、M、C $は、上述した意味します。
第二行は、$ N-1の$文字列、$ I $ $ {OPT} _i $ $ I $番目の最初の文字列は、演算子を表します。
第三行、N- $ $整数、最初の整数$ I $ $ $ X_I a_iを$ $美しい代表値。


出力フォーマット

プログラム、出力の$ $の整数をn-存在する場合は、$ I $ $整数は整数の間のスペースで区切って$ X_Iを表します。出力のいずれかでそのプログラムの様々ながある場合。何のプログラム、出力$ OVO $が存在しない場合。


サンプル

サンプル入力1:

4 2 3
XOR AND OR
2 1 1 1

出力例1:

3 2 1 2

サンプル入力2:

50 6 58
及びAND XORおよびAND OR AND XOR XOR AND XOR AND XOR OR XOR OR XOR OR OR XOR OR XOR XOR AND XOR OR ANDおよびXOR XOR AND XOR OR OR XOR XOR AND XOR XOR AND OR XOR XOR XOR AND XOR XOR排他的論理和XOR
3 2 5 3 3 1 3 3 2 3 1 3 1 5 2 5 2 3 5 2 3 5 2 4 5 2 3 2 4 3 2 3 3 0 4 1 2 2 3 6 5 2 2 2 2 3 4 3 5

サンプル出力2:

7 3 61 62 7 7 16 19 28 48 7 8 7 8 31 48 47 48 35 31 10 21 62 12 57 62 3 11 12 15 56 5 38 35 0 60 32 3 20 56 63 47 48 48 48 36 7 60 56 61


データ範囲とヒント

サンプル1点の説明:

$ 3 \ XOR \ 2 \と\ 1 \または\ 2 = 3 $、$および$ X_I値が制約を満たす、合成方法は、溶液です。

データ範囲:

すべてのデータ、$ 1 \ leqslant N \のleqslant {10} ^ 5,0 \ leqslant a_iを\ leqslant M \ leqslant 30 $のために。


問題の解決策

静かデータ範囲、大型の$ n $を見て、だけで$ 30 $メートル$ $。

その後、我々は、下位ビットのみと懸念$ 1 $の数を、見つける実際には、特定の値は重要ではありませんすることができます。

だから我々はまず、問題の解決策があるかどうかを設定します$ DPを考える[I] [J] $ $ iの前でオペアンプを$後に得られた$ jは$ $ 1 $演算結果があるかもしれないかどうかを示します。

$ X \ OPT \ Y = S $をとることができる、Xは、存在$、Y、Z $ A $ 1 $セットの$ Xは、Y、S $バイナリビット、セットの$ Xの\&Y $は$ W $あります$ 1 $、それは3つのケースに分けられます。

  $ \ alpha.AND:S = W、W \ leqslant X、\ leqslant Y、W、X + Y-W \ leqslantのM $

  $ \ beta.OR:S = X + Y-W、W \ leqslant X、\ leqslant Y、W、X + Y-W \ leqslantのM $

  $ \ gamma.XOR:S = X + Y-2W、W \ leqslant X、\ leqslant Y、W、X + Y-W \ leqslantのM $

それは$か$ 1 $ができるように、私たちは$ DP [n]は[C]を見てする必要があります。

されるのは、(すべてのデータポイントは、OVO $ $ません後に)実現可能なケースを考えてみよう、事前に$を設定する[I] [J] $は計算結果を示し、$ Jフロントで$ I $ OPは$ 1 $を$後に得られました旧$ I-1から転送されたどのように多くの$ 1 $の計算は、あなたが頼むかもしれない$の後に、状況の良い品種が、その後どのように行う、オーバー転送することができませんでしたか?実際には、我々は唯一のケースを必要とするので、私たちはただ転送する方法を記録する必要があります。

だから、それを計算する方法への答え?

我々は同様に$ BFSの$、$用のPOS $パスを算出した現在位置を示す2つのパラメータを使用する場合があり、$状態$は電流演算後の結果を示しています。

便宜上、設定:$あらかじめ\オプト\今=状態$。

だから我々は今、見つけるだろう、この計算ステップ、いくつかの$ 1 $(一時的に$ Y_I $を設定)と$ X_I $の計算結果の結果を知って十分に見えますが、弾丸をかむと押し下げ十分すぎるほど。

  $\alpha.AND:$我们可以这样想,先使$pre$和$now$凑出$state$中所有的$1$,然后多出来的不要重复就好啦,实现起来也非常简单。

  $\beta.OR:$我的思路就是,$pre$从前枚举所有$state$的$1$,$now$从后往前枚举所有$state$的$1$,为什么这样是正确的呢?因为我们走到这一步,已经保证了答案的合法,所以这么肆无忌惮的操作一定是可行的。

  $\gamma.XOR:$依然是枚举$state$中的$1$,然后看$x_i$和$y_i$谁更大,用大的去填$state$中的$1$,填完之后只要选一样的$1$即可,那么你还可能会问,如果填完之后$x_i$和$y_i$不一样怎么办呢?还是上面的那句话,路都走到这儿了,结果肯定合法。

我们就这样,一步一步的往前找就能找到答案啦,然后倒序输出即可。

时间复杂度:$\Theta(n\times m^2)$。

期望得分:$100$分。

实际得分:$100$分。


代码时刻

#include<bits/extc++.h>
using namespace std;
int n,m,c,x;
int pre[200001][50];
int cz[200001],a[200001];
bitset<50> bit;
bool vis[50];
void getans(int pos,int state)
{
	if(pos==1){printf("%d ",state);return;}
	bit=state;
	int gs=bit.count();
	int x=pre[pos][gs];
	int y=a[pos];
	int pr=0;
	int nw=0;
	memset(vis,0,sizeof(vis));
	switch(cz[pos])
	{
		case 1:
			for(int i=0;i<m;i++)if(state&(1<<i)){vis[i]=1;x--;y--;pr|=(1<<i);nw|=(1<<i);}
			for(int i=0;i<m&&x;i++)if(!vis[i]){x--;pr|=(1<<i);vis[i]=1;}
			for(int i=0;i<m&&y;i++)if(!vis[i]){y--;nw|=(1<<i);}
			break;
		case 2:
			for(int i=0;i<m&&x;i++)if(state&(1<<i)){x--;pr|=(1<<i);}
			for(int i=m-1;i>=0&&y;i--)if(state&(1<<i)){y--;nw|=(1<<i);}
			break;
		case 3:
			for(int i=0;i<m;i++)if(state&(1<<i)){if(x>y){x--;vis[i]=1;pr|=(1<<i);}else{y--;vis[i]=1;nw|=(1<<i);}}
			for(int i=0;i<m&&x&&y;i++)if(!vis[i]){x--;y--;pr|=(1<<i);nw|=(1<<i);}
	}
	getans(pos-1,pr);
	printf("%d ",nw);
}
int main()
{
	scanf("%d%d%d",&n,&m,&c);
	bit=c;
	x=bit.count();
	for(int i=2;i<=n;i++)
	{
		char opt[5];
		scanf("%s",opt+1);
		switch(opt[1])
		{
			case 'A':cz[i]=1;break;
			case 'O':cz[i]=2;break;
			case 'X':cz[i]=3;break;
		}
	}
	for(int i=1;i<=n;i++)
		scanf("%d",&a[i]);
	memset(pre,-1,sizeof(pre));
	pre[1][a[1]]=0;
	for(int i=2;i<=n;i++)
		for(int j=0;j<=m;j++)
			if(pre[i-1][j]!=-1)
				switch(cz[i])
				{
					case 1:for(int k=max(a[i]+j-m,0);k<=min(a[i],j);k++)pre[i][k]=j;break;
					case 2:for(int k=max(a[i],j);k<=min(a[i]+j,m);k++)pre[i][k]=j;break;
					case 3:for(int k=abs(j-a[i]);k<=min(j+a[i],2*m-j-a[i]);k+=2)pre[i][k]=j;break;
				}
	getans(n,c);
	return 0;
}

rp++

おすすめ

転載: www.cnblogs.com/wzc521/p/11370302.html