Codeforces Round#630(Div。2) 試合数12012
[codeforces 1332E]高さすべて同じパリティ構築+順列+高速べき+二項定理+乗法的逆
一般的なカタログについては、https://blog.csdn.net/mrcrack/article/details/103564004を参照してください
オンライン評価用アドレスhttps://codeforces.com/contest/1332/problem/E
問題 | ただ | 評決 | 時間 | 記憶 |
---|---|---|---|---|
E-すべて同じ高さ | GNU C ++ 11 | 受け入れた | 31ミリ秒 | 100 KB |
1.質問を理解する
四角の付け方、タイトルの理解も大きな問題です。
2つの隣接するセルに1つの立方体を積み上げます。この文を理解する方法は、下の図の操作1に従って理解するのは依然として困難です。
現時点で必要なのは忍耐、またはキーワードを把握することです。
最初はai、jの立方体がセル(i、j)に積み上げられます。この文は非常に重要です。セルは場所を定義し、多くの立方体を同じセルに配置できます。
上記の2つの文を英語と組み合わせると、質問の意味を読むことができるはずです。
これで、行iと列jに[i] [j]の正方形を持つn * mの正方形があります。
次の操作は何度でも実行できます。
1.1。(i、j)を選択して、[i] [j]に2を追加します。
1.2。隣接する2つの正方形を選択し、正方形の数に1を加えます。
ここで、最初のa [i] [j]は[L、R]の任意の数にすることができます。任意の数の操作の後で、すべてのa [i] [j]を同じにすることができる初期スキームの数を尋ねます。
2.アイデアはhttps://www.cnblogs.com/qieqiemin/p/12614527.htmlから取得され、個々のエラーが修正されます
2.1操作2はパリティを変更せず、同じパリティの数は操作2によって等しい数に変更する必要があるため、n ∗ m
ラティスのパリティのみが考慮されます。質問は、2つの隣接するラティスを選択してそれらのパリティを反転させ、最後にラティス全体のパリティを一致させることができるかどうかに変換できます。
これは古典的な問題であり、解決策は次のとおりです。すべての奇数と偶数が奇数であることは現実的ではありません。それ以外の場合は可能です。
赤は奇数、白は偶数です。
これを1つの操作(操作1)にすることができます。
奇数を特別な位置に移動した後、残りの偶数の数cntは偶数であるため、cnt / 2フリップ操作(操作1)を使用して次のようになります。
すべて赤(奇数)になり、上の図の1は最初の操作、2は2番目の操作、3は3番目の操作、4は4番目の操作を表します。
奇数と偶数の少なくとも一方が偶数であれば、この方法で同じパリティに変更できます。
(R-L + 1)^ nmは次のように説明されます:各位置は次のような値を取ることができます
L、L + 1、L + 2、......、R-1、R、R-L + 1通りあり、合計nmの位置があり、配置と組み合わせの乗算の原理に従って、タイプの数は(R -L + 1)^ nm
2.2それ以外の場合、この時点でn ∗ mは偶数であり、aを[L、R]の奇数の数とし、bを[L、R]の偶数の数とする。
二項定理をマスターしている場合は、上記の方程式の右端の方程式が理解できるはずです。
2.3。a + b = R-L + 1
R-L + 1が奇数の場合、| ab | = 1; R-L + 1が偶数の場合、| ab | = 0。
| ab |の値の起源は、例として検討できます。
1、2、3、4、5には2つの偶数、3つの奇数、R-L + 1 = 5、| ab | = 1
1、2、3、4、5、6には3つの偶数と3つの奇数があり、R-L + 1 = 6、| ab | = 0
2、3、4、5、6、および2つの奇数には3つの偶数があります。R-L+ 1 = 5、| ab | = 1
2、3、4、5、6、7には3つの偶数と3つの奇数があり、R-L + 1 = 6、| ab | = 0
2.4。2の逆数を計算することを忘れないでください。
ACコードは以下の通りです
#include <stdio.h>
#define LL long long
#define mod 998244353
LL quick_pow(LL a,LL b){//快速幂
LL ans=1;
while(b){
if(b&1)ans=ans*a%mod;
a=a*a%mod;
b>>=1;
}
return ans;
}
int main(){
LL n,m,L,R,x,ans;
scanf("%lld%lld%lld%lld",&n,&m,&L,&R);
x=R-L+1;
if(n*m%2==1)printf("%lld\n",quick_pow(x,n*m));
else{//n*m%2==0
//a奇数个数,b偶数个数 a+b=R-L+1, |a-b|=1或0,若R-L+1奇数,为1,否则为0
ans=quick_pow(x,n*m)+((x&1)?1:0);//((x&1)?1:0)计算(a-b)^nm
ans=ans*quick_pow(2,mod-2)%mod;//关于2的乘法逆元
printf("%lld\n",ans);
}
return 0;
}