SRM382 div2 hard
難しかった。
まずある数列の
(偶数番目の要素の和)=(奇数番目の要素の和)である集合をP
(前半の和)=(後半の和)である集合をQとする
DP[i][j]をi個の要素を持ち和がjである数列の数だとする(並び替えは違うものとする)
するとn(P)+n(Q)はDPで求められる。(*1)
次にn(P∩Q)を求める
前半K個の和をhalf、その中で偶数番目のものの和をquarterとする
(*2)
それでn(P)+n(Q)-n(P∩Q)を返す
#include <cstring> #include <string> #define MOD 999983 typedef long long LL; using namespace std; class CharmingTicketsEasy { public: LL DP[70][500]; int count(int K, string good) { memset(DP,0,sizeof(DP)); DP[0][0]=1; for(int i=0;i<K;i++) for(int j=0;j<460;j++) for(int k=0;k<(int)good.size();k++) { DP[i+1][j+good[k]-'0']+=DP[i][j]; DP[i+1][j+good[k]-'0']%=MOD; } LL U=0; for(int i=0;i<460;i++) //n(P)+n(Q)をUとしている U=(U+(DP[K][i]*DP[K][i])*2)%MOD; //*1 LL P=0; for(int half=0;half<460;half++) for(int quarter=0;quarter<=half;quarter++) { LL a=DP[K-K/2][quarter]*DP[K/2][half-quarter]; a%=MOD; //Pはn(P∩Q) P=(P+a*a)%MOD; //*2 } return ((U-P)%MOD+MOD)%MOD; } };