D.ジョンとオーブ(確率dp、2200)

トピックポータル

質問:ボールはk種類あり、1種類のボールが毎日同じ確率でランダムに生成され、収集されます。q回の問い合わせの場合、毎回1 pを尋ね、少なくとも何日か尋ねます。k個のボールをすべて集めた確率はp 2000 \ frac {p} {2000}以上です。2 0 0 0P。(k、q、p <= 1000 k、q、p <= 1000k q p<=1 0 0 0

アイデア:私たちはセットF [i]の[j]をF [i]の[J]f[i][j]为前 i i i日でjjを収集jが卵を繁殖させる確率、次にf [i] [j] f [i] [j]f [ i ] [ j ]転送するには、次の2つの方法があります。

  1. [i≥j]:f [i] [j] = f [i − 1] [j − 1] +(k − j + 1)/ k [i≥j]:f [i] [j] = f [i-1] [j-1] +(k-j + 1)/ k [私はj ]f [ i ] [ j ]=f [ i1 ] [ j1 ]+kj+1 / k
  2. [i −1≥j]:f [i] [j] = f [i − 1] [j] + j / k [i-1≥j]:f [i] [j] = f [i-1 ] [j] + j / k [私は1j ]f [ i ] [ j ]=f [ i1 ] [ j ]+j / k

そのため、F [i]の[j]をF [i]の[J]f[i][j]只与 f [ i − 1 ] [ j ] f[i-1][j] f [ i1 ] [ j ]f [i − 1] [j − 1] f [i-1] [j-1]f [ i1 ] [ j1 ]関連性がある、つまり、上位層にのみ関連しているため、配列をスクロールして1つの次元を最適化することを検討できます(2つの次元を強制的に開くこともできますが、最適化された時空間パフォーマンスは以前よりも大幅に向上しています最適化)

ans [i]を使用して、p = iの場合に必要な最小日数を表します。そのため、PP最大pは1000なので、ans [1000]の処理が終了したら、前処理を終了できます。

コード:

#include<bits/stdc++.h>
#define endl '\n'
#define null NULL
#define ls p<<1
#define rs p<<1|1
#define fi first
#define se second
#define mp make_pair
#define pb push_back
#define ll long long
#define int long long
#define lowbit(x) x&-x
#define pii pair<int,int>
#define ull unsigned long long
#define pdd pair<double,double>
#define sz(x) (int)(x).size()
#define all(x) (x).begin(),(x).end()
#pragma GCC optimize("-Ofast","-funroll-all-loops")
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
char *fs,*ft,buf[1<<20];
#define gc() (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<20,stdin),fs==ft))?0:*fs++;
inline int read()
{
    
    
    int x=0,f=1;
    char ch=gc();
    while(ch<'0'||ch>'9')
    {
    
    
        if(ch=='-')
            f=-1;
        ch=gc();
    }
    while(ch>='0'&&ch<='9')
    {
    
    
        x=x*10+ch-'0';
        ch=gc();
    }
    return x*f;
}
using namespace std;
const int N=3e6+666;
const int inf=0x3f3f3f3f;
const int mod=998244353;
const double eps=1e-7;
const double PI=acos(-1);

double f[11111];
int ans[N],cnt=0;

signed main()
{
    
    
    int k,q;
    cin>>k>>q;
    f[0]=1;
    for(int i=1;cnt<=1000;i++)
    {
    
    
        for(int j=min(i,k);j>=1;j--)
            f[j]=(f[j-1]*(k-(j-1))+f[j]*j)/k;
        while(i>=k&&f[k]*2000>=cnt)
            ans[cnt++]=i;
        f[0]=0;
    }
    while(q--)
    {
    
    
        int p;cin>>p;
        cout<<ans[p]<<endl;
    }
    return 0;
}

}

おすすめ

転載: blog.csdn.net/Joker_He/article/details/110500968