SRM457 div1 medium

0:何種類の数字を使うか決める
1:二個つかう数字の余りを決める(組み合わせを求める)
2:一個使う数字の余りを決める(同上)
3:一個使う方は大きい方を使うか小さい方を使うかがある

#include <algorithm>
#include <cstring>

typedef long long LL;
using namespace std;

class TheHexagonsDivOne
{
	public:

		int board[7];
		LL cache[200][200];

		LL C(int n,int r)
		{
			if(n<r)
				return 0;
			if(cache[n][r]!=-1)
				return cache[n][r];
			if(r==0 || n==r)
				return cache[n][r]=1;
			return cache[n][r]=C(n-1,r)+C(n-1,r-1);
		}

		LL calc()
		{
			LL r=0;
			int o[7];
			for(int i=0;i<7;i++)
				o[i]=i;
			do
			{
				int bo[7];
				for(int i=0;i<7;i++)
					bo[i]=board[o[i]];
				bool b=true;
				for(int i=1;i<5 && b;i++)
					b=(b && bo[i-1]!=bo[i]);
				b=(b && bo[0]!=bo[5] && bo[4]!=bo[5]);
				for(int i=0;i<6 && b;i++)
					b=(b && bo[i]!=bo[6]);
				if(b)
					r++;
			}while(next_permutation(o,o+7));
			return r;
		}

		LL count(int n)
		{
			memset(cache,-1,sizeof(cache));
			LL ans=0;
			
			board[0]=0,board[1]=1,board[2]=2,board[3]=3,board[4]=4,board[5]=5,board[6]=6;
			printf("same=0 calc()=%lld\n",calc()/6);
			ans+=C(n,0)*C(n,7)*(LL)(1<<7)*calc()/6;
			
			board[0]=0,board[1]=0,board[2]=2,board[3]=3,board[4]=4,board[5]=5,board[6]=6;
			printf("same=1 calc()=%lld\n",calc()/6);
			ans+=C(n,1)*C((n-1),5)*(LL)(1<<5)*calc()/6;
			
			board[0]=0,board[1]=0,board[2]=2,board[3]=2,board[4]=4,board[5]=5,board[6]=6;
			printf("same=2 calc()=%lld\n",calc()/6);
			ans+=C(n,2)*C((n-2),3)*(LL)(1<<3)*calc()/6;

			board[0]=0,board[1]=0,board[2]=2,board[3]=2,board[4]=4,board[5]=4,board[6]=6;
			printf("same=3 calc()=%lld\n",calc()/6);
			ans+=C(n,3)*C((n-3),1)*(LL)(1<<1)*calc()/6;
			return ans;
		}
};

残り99問