E99 线性DP+前缀和优化 P3643 [APIO2016] 划艇
视频链接:E99 线性DP+前缀和优化 P3643 [APIO2016] 划艇_哔哩哔哩_bilibili




参考:G13 同余式 乘法逆元 费马小定理 - 董晓 - 博客园
// 线性DP+前缀和优化 O(n^3) #include<bits/stdc++.h> using namespace std; #define int long long const int N=505,M=1e9+7; int n,m,ans; int a[N],b[N],x[N<<1],inv[N],C[N],f[N],g[N]; int qpow(int a,int b){ int s=1; while(b){ if(b&1) s=s*a%M; a=a*a%M; b>>=1; } return s; } signed main(){ scanf("%d",&n); for(int i=1;i<=n;i++){ scanf("%d%d",&a[i],&b[i]); x[i]=a[i]; //左闭 x[i+n]=++b[i]; //右开 } sort(x+1,x+1+2*n); m=unique(x+1,x+1+2*n)-x-1; for(int i=1;i<=n;i++){ a[i]=lower_bound(x+1,x+1+m,a[i])-x; b[i]=lower_bound(x+1,x+1+m,b[i])-x; } f[0]=g[0]=C[0]=inv[1]=1; for(int i=2;i<=n;i++) inv[i]=qpow(i,M-2); for(int j=1;j<m;j++){ //第j区间 int L=x[j+1]-x[j]; for(int i=1;i<=n;i++) C[i]=C[i-1]*(L+i-1)%M*inv[i]%M; for(int i=n;i;i--){ //前i学校 if(a[i]<=j&&b[i]>=j+1){ for(int s=1,k=i-1;k>=0;k--){ f[i]=(f[i]+g[k]*C[s])%M; if(a[k]<=j&&b[k]>=j+1) s++; } } g[i]=f[i]; //前缀和 } } for(int i=1;i<=n;i++) ans=(ans+f[i])%M; printf("%d\n",ans); }
// 线性DP+前缀和优化 O(n^3) #include<bits/stdc++.h> using namespace std; #define int long long const int N=505,M=1e9+7; int n,m,ans; int a[N],b[N],x[N<<1],inv[N],C[N],f[N]; int qpow(int a,int b){ int s=1; while(b){ if(b&1) s=s*a%M; a=a*a%M; b>>=1; } return s; } signed main(){ scanf("%d",&n); for(int i=1;i<=n;i++){ scanf("%d%d",&a[i],&b[i]); x[i]=a[i]; //左闭 x[i+n]=++b[i]; //右开 } sort(x+1,x+1+2*n); m=unique(x+1,x+1+2*n)-x-1; for(int i=1;i<=n;i++){ a[i]=lower_bound(x+1,x+1+m,a[i])-x; b[i]=lower_bound(x+1,x+1+m,b[i])-x; } f[0]=C[0]=inv[1]=1; for(int i=2;i<=n;i++) inv[i]=qpow(i,M-2); for(int j=1;j<m;j++){ //第j区间 int L=x[j+1]-x[j]; for(int i=1;i<=n;i++) C[i]=C[i-1]*(L+i-1)%M*inv[i]%M; for(int i=n;i;i--){ //前i学校 if(a[i]<=j&&b[i]>=j+1){ for(int s=1,k=i-1;k>=0;k--){ f[i]=(f[i]+f[k]*C[s])%M; if(a[k]<=j&&b[k]>=j+1) s++; } } } } for(int i=1;i<=n;i++) ans=(ans+f[i])%M; printf("%d\n",ans); }
// 线性DP+前缀和优化 O(n^3) #include<bits/stdc++.h> using namespace std; #define int long long const int N=505,M=1e9+7; int n,m,ans; int a[N],b[N],x[N<<1],inv[N],C[N],f[N]; signed main(){ scanf("%d",&n); for(int i=1;i<=n;i++){ scanf("%d%d",&a[i],&b[i]); x[i]=a[i]; //左闭 x[i+n]=++b[i]; //右开 } sort(x+1,x+1+2*n); m=unique(x+1,x+1+2*n)-x-1; for(int i=1;i<=n;i++){ a[i]=lower_bound(x+1,x+1+m,a[i])-x; b[i]=lower_bound(x+1,x+1+m,b[i])-x; } f[0]=C[0]=inv[1]=1; for(int i=2;i<=n;i++) inv[i]=(M-M/i)*inv[M%i]%M; for(int j=1;j<m;j++){ //第j区间 int L=x[j+1]-x[j]; for(int i=1;i<=n;i++) C[i]=C[i-1]*(L+i-1)%M*inv[i]%M; for(int i=n;i;i--){ //前i学校 if(a[i]<=j&&b[i]>=j+1){ for(int s=1,k=i-1;k>=0;k--){ f[i]=(f[i]+f[k]*C[s])%M; if(a[k]<=j&&b[k]>=j+1) s++; } } } } for(int i=1;i<=n;i++) ans=(ans+f[i])%M; printf("%d\n",ans); }
// 线性DP+前缀和优化 O(n^3) 滚动数组&正序枚举 #include<bits/stdc++.h> using namespace std; #define int long long const int N=505,M=1e9+7; int n,m,ans; int a[N],b[N],x[N<<1],inv[N],C[N],f[N],g[2][N]; int qpow(int a,int b){ int s=1; while(b){ if(b&1) s=s*a%M; a=a*a%M; b>>=1; } return s; } signed main(){ scanf("%d",&n); for(int i=1;i<=n;i++){ scanf("%d%d",&a[i],&b[i]); x[i]=a[i]; //左闭 x[i+n]=++b[i]; //右开 } sort(x+1,x+1+2*n); m=unique(x+1,x+1+2*n)-x-1; for(int i=1;i<=n;i++){ a[i]=lower_bound(x+1,x+1+m,a[i])-x; b[i]=lower_bound(x+1,x+1+m,b[i])-x; } f[0]=g[0][0]=g[1][0]=C[0]=inv[1]=1; for(int i=2;i<=n;i++) inv[i]=qpow(i,M-2); for(int j=1;j<m;j++){ //第j区间 int L=x[j+1]-x[j]; for(int i=1;i<=n;i++) C[i]=C[i-1]*(L+i-1)%M*inv[i]%M; int s=0,t; for(int i=1;i<=n;i++){ //前i学校 if(a[i]<=j&&b[i]>=j+1){ t=++s; for(int k=0;k<=i-1;k++){ if(a[k]<=j&&b[k]>=j+1) t--; f[i]=(f[i]+g[j&1][k]*C[t])%M; } } g[j+1&1][i]=f[i]; //前缀和 } } for(int i=1;i<=n;i++) ans=(ans+f[i])%M; printf("%d\n",ans); }
浙公网安备 33010602011771号