これはコンテストの問題です(ACM ICPC南アメリカ2015)、問題が最も難しいです。どのようにこのハードコンビナトリアルを解決するには?
概要:与えられる整数N及びK、長さのNが≤整数からなる配列の数をカウントI≤ Kであり、その中の任意のx ENCE iがjのがI < JとI = X満たし、一対が存在しなければならない - 1とJ X = 、すなわち最後のxの前には、ある時点でx-1が続きます。
例:N = 1000とK = 100溶液については、265428620モジュロ(10 + 7)と合同であるべきです。その他の例と詳細はthe problem descriptionにあります。
私は自分の知識のすべてを試しましたが、それを行う方法を知るためのポインタが必要です。私はパターンを見つけるために強引な力でいくつかのリストを印刷しましたが、私は成功しませんでした。
私はこの問題の正しい解決方法を得るためのアルゴリズムまたは数式を探しています。それはどんな言語でもよい。
EDIT:
私は、インターネット(この問題を説明し、誰か)で見つかった式を使用して問題を解決しました。しかし、私はそれをプログラムしたからといって、理解しているわけではないので、問題は開いたままです。私のコードは、(オンライン裁判官が受理を返します)ここにある:
#include <bits/stdc++.h>
using namespace std;
typedef long long int ll;
ll mod = 1e9+7;
ll memo[5001][5001];
ll dp(int n, int k){
// K can't be greater than N
k = min(n, k);
// if N or K is 1, it means there's only one possible list
if(n <= 1 || k <= 1) return 1;
if(memo[n][k] != -1) return memo[n][k];
ll ans1 = (n-k) * dp(n-1, k-1);
ll ans2 = k * dp(n-1, k);
memo[n][k] = ((ans1 % mod) + (ans2 % mod)) % mod;
return memo[n][k];
}
int main(){
int n, q;
for(int i=0; i<5001; i++)
fill(memo[i], memo[i]+5001, -1);
while(scanf("%d %d", &n, &q) == 2){
for(int i=0; i<q; i++){
int k;
scanf("%d", &k);
printf("%s%lld", i==0? "" : " ", dp(n, k));
}
printf("\n");
}
return 0;
}
最も重要な行は再帰呼び出しされ、特に、ここでは、これらの線
ll ans1 = (n-k) * dp(n-1, k-1);
ll ans2 = k * dp(n-1, k);
memo[n][k] = ((ans1 % mod) + (ans2 % mod)) % mod;
あなたはこのページに必要なものの全体の定義を入れる必要があります。質問内容へのリンクは悪いとみなされます。どのように結果を見たいですか?たとえば、Pythonコードを答えにすることはできますか? –
はい、答えを見つけるコードや数式は、私が感謝する答えです。私はそれを解決したり分析したりするにはどうすればいいのか知りたいだけです。 –
問題は非常に複雑で、私は15分間問題を理解しようとして過ごしました。多分私はそれを後で試してみるだろう。 –