確かに今日のyukicoderは聞きなれない曲が多い気がする。
http://yukicoder.me/problems/no/498
問題
2次元のグリッド上で、K種類のクリスタルを使いワープしていくことを考える。
i番目のクリスタルを使うと、現在の位置から(X[i],Y[i])だけ移動した相対位置のグリッドに移動できる。
i番目のクリスタルはN[i]個あり、1個のクリスタルで1回移動できる。
クリスタルをいくつか利用し、(0,0)から(Gx,Gy)に移動する際、使用するクリスタルの並び順は何通りあるか。
なお、同種のクリスタルは互いに区別されない。
解法
K,N[i]が小さいので、まずは並び順を無視してクリスタルの利用回数を総当たりし、(0,0)→(Gx,Gy)に移動できるケースを求めよう。
各クリスタルの使用回数をM[i]とすると、それらの並び順は通りである。
ll mo=1000000007; const int NUM_=2000003; static ll fact[NUM_+1],factr[NUM_+1],inv[NUM_+1]; ll ret=0; int GX,GY,K; int X[10],Y[10],N[10]; vector<int> R; void dfs(int id, int cx,int cy) { if(id==K) { if(cx!=GX || cy!=GY) return; int sum=0; FORR(r,R) sum+=r; ll t = fact[sum]; FORR(r,R) t = t*factr[r]%mo; (ret = ret + t)%=mo; } else { int i; FOR(i,N[id]+1) { R.push_back(i); dfs(id+1,cx+X[id]*i,cy+Y[id]*i); R.pop_back(); } } } void solve() { int i,j,k,l,r,x,y; string s; inv[1]=fact[0]=factr[0]=1; for (int i=2;i<=NUM_;++i) inv[i] = inv[mo % i] * (mo - mo / i) % mo; for (int i=1;i<=NUM_;++i) fact[i]=fact[i-1]*i%mo, factr[i]=factr[i-1]*inv[i]%mo; cin>>GX>>GY>>K; FOR(i,K) cin>>X[i]>>Y[i]>>N[i]; dfs(0,0,0); cout<<ret<<endl; }
まとめ
次回で500問になりそうね。