escription
在首尔城中,汉江横贯东西。在汉江的北岸,从西向东星星点点地分布着个划艇学校,编号依次为到。每个学校都
拥有若干艘划艇。同一所学校的所有划艇颜色相同,不同的学校的划艇颜色互不相同。颜色相同的划艇被认为是一
样的。每个学校可以选择派出一些划艇参加节日的庆典,也可以选择不派出任何划艇参加。如果编号为的学校选择
派出划艇参加庆典,那么,派出的划艇数量可以在Ai至Bi之间任意选择(Ai<=Bi)。值得注意的是,编号为i的学
校如果选择派出划艇参加庆典,那么它派出的划艇数量必须大于任意一所编号小于它的学校派出的划艇数量。输入
所有学校的Ai、Bi的值,求出参加庆典的划艇有多少种可能的情况,必须有至少一艘划艇参加庆典。两种情况不同
当且仅当有参加庆典的某种颜色的划艇数量不同
Input
第一行包括一个整数N,表示学校的数量。接下来N行,每行包括两个正整数,用来描述一所学校。其中第行包括的
两个正整数分别表示Ai,Bi(1<=Ai<=Bi<=10^9),N<=500
Output
输出一行,一个整数,表示所有可能的派出划艇的方案数除以1,000,000,007得到的余数
Sample Input
2
1 2
2 3
1 2
2 3
Sample Output
7
想出来之后不难,挺基础的。
由于AI,BI范围实在太大,所以要考虑离散化,最多一共有2*n-1个可行区间。
用lenj表示区间长度。
然后dp方程就很显然了。
注意,每个学校可以选择不放,所以每次dp方程不用清空,直接累加就好。
思路很简单,写完之后发现一个致命的问题。
唉?TLE了?
怎么办???
卡常,换成register int,加上各种优化。
详细见代码。
#include<bits/stdc++.h> using namespace std; const int mod=1000000007; #define ll long long #ifdef ONLINE_JUDGE char *TT,*mo,but[(1<<15)+2]; #define getchar() ((TT==mo&&(mo=(TT=but)+fread(but,1,1<<15,stdin)),TT==mo)?0:*TT++) #endif inline int read(){ int x=0,c=0,f=1; for(;c<'0'||c>'9';c=getchar())f=c!='-'; for(;c>='0'&&c<='9';c=getchar())x=x*10+c-'0'; return f?x:-x; } int dp[1010][510]; int p[1010]; int len[1010]; int inv[1010]; int a[510],b[510]; int d[1010]; int cnt; int ct[1010]; int n; int main(){ n=read(); register int i,j,k; for(i=1;i<=n;i++)a[i]=read()-1,b[i]=read(); for(i=1;i<=n;i++){ d[++cnt]=a[i]; d[++cnt]=b[i]; } sort(d+1,d+cnt+1); cnt=unique(d+1,d+cnt+1)-d-1; for(i=2;i<=cnt;i++){ len[i-1]=d[i]-d[i-1]; } inv[1]=1; for(i=2;i<=n;i++)inv[i]=1ll*inv[mod%i]*(mod-mod/i)%mod; for(i=1;i<=n;i++)a[i]=lower_bound(d+1,d+cnt+1,a[i])-d,b[i]=lower_bound(d+1,d+cnt+1,b[i])-d; for(i=0;i<cnt;i++)p[i]=1; for(i=1;i<=n;++i){ for(j=a[i];j<b[i];++j){ ct[j]++; for(k=ct[j];k>=2;--k){ dp[j][k]=(dp[j][k]+1ll*dp[j][k-1]*(len[j]+1-k)%mod*inv[k]%mod)%mod; } dp[j][1]=(dp[j][1]+1ll*p[j-1]*len[j])%mod; } for(j=a[i];j<cnt;++j){ p[j]=p[j-1]; for(k=1;k<=ct[j];k++) p[j]=(p[j]+dp[j][k])%mod; } } cout<<p[cnt-1]-1; return 0; }