POJ 3046 Ant Counting
DP。
设dp[i][j]表示:选i个数字,最大的数字是j的有几种。
注意坑点:对1000000取模之后dp[i][j]可能出现负的,需要加上一个mod
后台数据有点水了,事实上按我这样做的话,时间复杂度和空间复杂度都是一亿,但后台数据并没有那么强。。。
#include<cstdio> #include<cstring> #include<cmath> #include<queue> #include<algorithm> using namespace std; const int maxn=1000+10; int T,A,S,B; int num[maxn]; int dp[3000+10][maxn]; int sum[3000+10][maxn]; int f[3000+10][maxn]; const int mod=1000000; void read() { for(int i=1;i<=A;i++) { int x; scanf("%d",&x); num[x]++; } } void init() { memset(num,0,sizeof num); memset(f,0,sizeof f); memset(sum,0,sizeof sum); memset(dp,0,sizeof dp); } void work() { for(int i=1;i<=B;i++) { for(int j=1;j<=T;j++) { if(i==1) dp[i][j]=1; else if(j==1) { if(num[j]>=i) dp[i][j]++; } else { int r=min(num[j],i-1); dp[i][j]=(f[i-1][j-1]-f[i-r-1][j-1])%mod+mod; if(num[j]>=i) dp[i][j]=(dp[i][j]+1)%mod; } sum[i][j]=(sum[i][j-1]+dp[i][j])%mod; f[i][j]=(f[i-1][j]+sum[i][j])%mod; } } int ans=0; for(int i=S;i<=B;i++) for(int j=1;j<=T;j++) ans=(ans+dp[i][j])%mod; printf("%d\n",ans); } int main() { while(~scanf("%d%d%d%d",&T,&A,&S,&B)) { init(); read(); work(); } return 0; }