典型90問
次の典型90問へ
前の典型90問へ
典型90問 086 Snuke's Favorite Arrays(★5)
C#のソース
using System;
using System.Collections.Generic;
using System.Linq;
class Program
{
static string InputPattern = "InputX";
static List<string> GetInputList()
{
var WillReturn = new List<string>();
if (InputPattern == "Input1") {
WillReturn.Add("4 2");
WillReturn.Add("1 2 3 50");
WillReturn.Add("2 3 4 45");
//13
}
else if (InputPattern == "Input2") {
WillReturn.Add("8 2");
WillReturn.Add("2 3 6 1152886174205865983");
WillReturn.Add("1 2 8 1116611213275394047");
//395781543
}
else {
string wkStr;
while ((wkStr = Console.ReadLine()) != null) WillReturn.Add(wkStr);
}
return WillReturn;
}
const long Hou = 1000000007;
static long mN;
struct XYZWInfoDef
{
internal long X;
internal long Y;
internal long Z;
internal long W;
}
static List<XYZWInfoDef> mXYZWInfoList = new List<XYZWInfoDef>();
static long mMaxW;
static void Main()
{
List<string> InputList = GetInputList();
long[] wkArr = { };
Action<string> SplitAct = pStr =>
wkArr = pStr.Split(' ').Select(pX => long.Parse(pX)).ToArray();
SplitAct(InputList[0]);
mN = wkArr[0];
foreach (string EachStr in InputList.Skip(1)) {
SplitAct(EachStr);
XYZWInfoDef WillAdd;
WillAdd.X = wkArr[0];
WillAdd.Y = wkArr[1];
WillAdd.Z = wkArr[2];
WillAdd.W = wkArr[3];
mXYZWInfoList.Add(WillAdd);
}
mMaxW = mXYZWInfoList.Max(pX => pX.W);
// 2べきのListを作成
DeriveBeki2List();
// ビットごとの0と1の全ての組み合わせ
IEnumerable<long[]> Query = RubyPatternClass<long>.RepeatedPermutation(new long[] { 0, 1 }, mN);
long Answer = 1;
// ビットごとに全ての組み合わせをチェックする
foreach (long EachBeki2 in mBeki2List) {
List<long[]> CurrBitArrList = Query.ToList();
foreach (XYZWInfoDef EachXYZWInfo in mXYZWInfoList) {
for (int I = CurrBitArrList.Count - 1; 0 <= I; I--) {
long WBit = EachXYZWInfo.W & EachBeki2;
long XBit = CurrBitArrList[I][EachXYZWInfo.X - 1];
long YBit = CurrBitArrList[I][EachXYZWInfo.Y - 1];
long ZBit = CurrBitArrList[I][EachXYZWInfo.Z - 1];
long Sign1 = Math.Sign(WBit);
long Sign2 = Math.Sign(XBit | YBit | ZBit);
if (Sign1 != Sign2) {
CurrBitArrList.RemoveAt(I);
}
}
}
Answer *= CurrBitArrList.Count;
Answer %= Hou;
}
Console.WriteLine(Answer);
}
// 2べきのList
static List<long> mBeki2List = new List<long>();
// 2べきのListを作成
static void DeriveBeki2List()
{
// ビットのループ
long CurrBeki2 = 1;
while (CurrBeki2 <= mMaxW) {
mBeki2List.Add(CurrBeki2);
CurrBeki2 *= 2;
}
}
}
#region RubyPatternClass
// Rubyの場合の数
internal static class RubyPatternClass<Type>
{
// 重複順列を返す
private struct JyoutaiDef_RepeatedPermutation
{
internal List<long> SelectedIndList;
}
internal static IEnumerable<Type[]> RepeatedPermutation(IEnumerable<Type> pEnum, long pR)
{
if (pR == 0) yield break;
Type[] pArr = pEnum.ToArray();
var Stk = new Stack<JyoutaiDef_RepeatedPermutation>();
JyoutaiDef_RepeatedPermutation WillPush;
for (int I = pArr.GetUpperBound(0); 0 <= I; I--) {
WillPush.SelectedIndList = new List<long>() { I };
Stk.Push(WillPush);
}
while (Stk.Count > 0) {
JyoutaiDef_RepeatedPermutation Popped = Stk.Pop();
// クリア判定
if (Popped.SelectedIndList.Count == pR) {
var WillReturn = new List<Type>();
Popped.SelectedIndList.ForEach(X => WillReturn.Add(pArr[X]));
yield return WillReturn.ToArray();
continue;
}
for (int I = pArr.GetUpperBound(0); 0 <= I; I--) {
WillPush.SelectedIndList = new List<long>(Popped.SelectedIndList) { I };
Stk.Push(WillPush);
}
}
}
}
#endregion
解説
BitORはビットごとに独立してるので
ビットごとに解候補が何通りあるかを求めて
積の法則を使ってます。