zoukankan      html  css  js  c++  java
  • 【模拟7.19】那一天我们许下约定(组合数学,DP)

    看了题目名字深切怀疑出题人是不是失恋了,然后出题折磨我们。然后这题就愉快的打了个暴力,最后莫名其妙wa20,伤心.....

    其实这题正解不是很难想,如果说把暴力的DP搞出来,正解也差不到哪去了,

    我们发现此题中暴力的话

    一层枚举D即天数,另一层枚举当前给过的饼干数j,然后还有一层枚举上一层的饼干数,(当然还可以通过前缀和删去一维)

    但是我们观察数据范围,发现D及其的大!!!!!!!

    显然枚举中不能出现D

    有一条显然的性质,如果你有N块饼干,那么最多给N天,每天给一块就会给完。

    那么我们第一维枚举至N,表示每一天一定给

    最后统计答案时(i:1~N)f[i][N]*C(D,i);即可

    (本题中D过大,所以不能用逆元,改用递推O(n)求,*(D-i)时要取模,不然会暴)

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<string>
     5 #include<cmath>
     6 #include<algorithm>
     7 #define ll long long
     8 using namespace std;
     9 #define MAXN 2010
    10 const ll mod=998244353;
    11 ll f[MAXN][MAXN];
    12 ll N,D,M;
    13 ll ni[MAXN],ni_c[MAXN];
    14 ll a[MAXN][MAXN];
    15 ll max1(ll x,ll y)
    16 {
    17    return (x>y)?x:y;
    18 }
    19 ll min1(ll x,ll y)
    20 {
    21    return (x<y)?x:y;
    22 }
    23 void work()
    24 {
    25    f[0][0]=1;a[0][0]=1;   
    26    for(ll i=1;i<=N;++i)
    27    {
    28        ll R=min(N,(M-1)*i);   
    29        for(ll j=1;j<=N;++j)
    30        {
    31            a[i-1][j]=(a[i-1][j-1]+f[i-1][j]+mod)%mod;
    32        }   
    33        for(ll j=i;j<=R;++j)
    34        {
    35            ll L=max1(i-1,j-M+1);
    36            /*for(ll k=L;k<=j-1;++k)
    37            {
    38               f[i][j]=(f[i][j]+f[i-1][k])%mod;
    39            }*/
    40            f[i][j]=(f[i][j]%mod+(a[i-1][j-1]-a[i-1][L-1]+mod)%mod+mod)%mod;
    41            //printf("f[%lld][%lld]=%lld
    ",i,j,f[i][j]);
    42        }
    43    }
    44    ll sum=0ll;ll ans=1ll;
    45    for(ll i=1;i<=N;++i)
    46    {
    47       if(i>D)continue;
    48       ans=(ans*((D-i+1)%mod)+mod)%mod;
    49       sum=(sum+(f[i][N]*(ans*ni_c[i]%mod+mod)+mod)%mod+mod)%mod;
    50       //printf("f=%lld C=%lld
    ",f[i][N],C(D,i));
    51    }
    52    printf("%lld
    ",sum%mod);
    53 }
    54 int main()
    55 {
    56  //  freopen("text.in","r",stdin);
    57  //  freopen("wa.out","w",stdout);
    58    ni_c[1]=1;ni[1]=1;
    59    ni_c[0]=1;ni[0]=1;
    60    for(ll i=2;i<=2000;++i)
    61    {
    62        ni[i]=((mod-mod/i)*ni[mod%i])%mod;
    63        ni_c[i]=(ni_c[i-1]*ni[i])%mod;
    64    }
    65    while(cin>>N>>D>>M)
    66    {
    67       if(N==0&&D==0&&M==0)break;
    68       memset(f,0,sizeof(f));
    69       memset(a,0,sizeof(a));
    70       work();
    71    }
    72 }
    View Code
  • 相关阅读:
    IntelliJ IDEA设置代码括号对齐方式
    cygwin完全安装步骤方法(过程图解)
    IntelliJ IDEA(2017)安装和破解
    ANDROID学习之路
    最新Android系统版本与API等级对应关系表
    Matlab 2016b 正式版下载
    山东省高等学校教师资格考试题库(附答案)
    Java中List集合去除重复数据的方法
    jquery判断选择元素是否存在
    人民币金额转化汉字的java写法
  • 原文地址:https://www.cnblogs.com/Wwb123/p/11221064.html
Copyright © 2011-2022 走看看