E比昨天更多的棒棒糖(Easy+Hrad)(華師網絡賽)(DP||母函數||背包優化)


Time limit per test: 2.0 seconds

Memory limit: 512 megabytes

唐納德先生的某女性朋友最近與唐納德先生同居。該女性朋友攜帶一 baby。該 baby 酷愛吃棒棒糖,且有一個奇怪的特性:今天吃的棒棒糖一定要比昨天的棒棒糖更多,至少要一樣多。如果棒棒糖少了,baby 就會很不高興;另外如果有連續 k 天棒棒糖的數量都是一樣的,baby 也會很不高興。

唐納德先生發現他的口袋里只有可憐的 n 元錢,他可以用 1 元錢買 1 根棒棒糖。他想用這些錢逗 baby 開心,這些錢可以不花完。他可以從某一天開始再也不買棒棒糖,把他的女性朋友和 baby 一起送回家;但是他絕對不能讓 baby 不高興,否則他的女性朋友可能對他做一些不和諧的事情。

唐納德先生想要知道,他總共有多少種買棒棒糖的方案,兩種方案不相同當且僅當總天數不相同,或者某一天買的棒棒糖數量不相同。唐納德先生知道這個問題對於聰明的你實在是太簡單了,所以他加了一個附加條件:他第一天必須買棒棒糖,而且至少買 x 根棒棒糖。

Input

一行三個整數 n,x,k

數據范圍約定:

  • 對於 Easy 檔:1n,x100,2k100
  • 對於 Hard 檔:1n,x104,2k104

Output

輸出答案模 998 244 353

Examples

input

3 1 2

output

4

input

1 1 2

output

1

input

4 2 3

output

4

Note

樣例 1:

有四種方案:

  • 第一天 1;
  • 第一天 2;
  • 第一天 3;
  • 第一天 1,第二天 2;

注意第一天和第二天都買 1 是不行的,因為連續兩天棒棒糖數量一樣,baby 就會很不高興。

題意:

把n表示成a1*p1+a2*p2+a3*p3...的形式,且滿足x<=a1<a2<a3..;0<p<K;

自己思路:

數的划分問題。

小數據,可以用DP或者母函數來解決,可以參考官方題解,這里不再累贅。

官方題解:

(ORZ,母函數優化背包)

 Easy版本,普通母函數

#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<memory.h>
#include<algorithm>
#include<cstring>
using namespace std;
const int Mod=998244353;
int c1[330],c2[330],ans,x,K,p;
int n,i,j,m,k;
void _get()
{  
    memset(c1,0,sizeof(c1));
    memset(c2,0,sizeof(c2));
    scanf("%d%d",&x,&K);
    for(k=0;k<K&&k*x<=n;k++) {
         c1[k*x]=1;
         ans=(ans+c1[k*x])%Mod;
    }
    for(i=x+1;i<=n;i++){
        for(j=0;j<=n;j++)
          for(k=0;k*i+j<=n&&k<K;k++) {
               c2[k*i+j]+=c1[j]; 
               if(k) ans=(ans+c1[j])%Mod;
            }
        for(k=0;k<=n;k++) {
            c1[k]=c2[k];    
            c2[k]=0;
        }
    }
    ans=(ans+Mod-1)%Mod;
}
int main()
{
  
    while(cin>>n) {
        ans=0;
        _get(); 
        cout<<ans<<endl;
    }
    return 0;
}

 

Hard版本,母函數優化背包。

左邊的用a表示,右邊的用b表示。 左邊和右邊分別是背包問題。

#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<cstring>
using namespace std;
const int Mod=998244353;
const int maxn=10100;
long long  a[maxn],b[maxn],c[maxn],ans;
int main()
{
    int n,x,k,i,j;
    scanf("%d%d%d",&n,&x,&k);
    a[0]=b[0]=1;
    
    for(i=x;i<=n;i++)
     for(j=n;j>=0;j--)
      if(j>=i*k) a[j]=(a[j]-a[j-i*k])%Mod;
      
    for(i=x;i<=n;i++)
     for(j=i;j<=n;j++)
       b[j]=(b[j]+b[j-i])%Mod;
    
    for(i=0;i<=n;i++)
     for(j=0;j<=n;j++)
      if(i+j<=n) c[i+j]=(c[i+j]+a[i]*b[j])%Mod;

     for(i=1;i<=n;i++)
       ans=((ans+c[i])%Mod+Mod)%Mod;
     
    printf("%lld\n",ans);
    return 0;
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM