dp专场既视感
T1.gift
有约束的背包。
先把原序列排序,从小到大,对于其中第x个元素,我们假设它是最小的没有被选的物品,那么小于a[x]的都要被强制选择。
这就会影响统计答案的区间,变成( m-s[i-1],m-s[i] ]。
其余正常转移即可。
#include<algorithm> #include<iostream> #include<cstdio> using namespace std; const int MAXN=1005; const int MOD=1e9+7; int f[MAXN]; int a[MAXN],s[MAXN]; int n,m,ans; int main(){ cin>>n>>m; f[0]=1; for(int i=1;i<=n;i++) cin>>a[i]; sort(a+1,a+1+n); for(int i=1;i<=n;i++) s[i]=s[i-1]+a[i]; for(int i=n;i>=1;i--){ for(int j=m-s[i-1];j>=0&&j>m-s[i];j--)(ans+=f[j])%=MOD; for(int j=m;j>=a[i];j--)(f[j]+=f[j-a[i]])%=MOD; } if(s[n]<=m) ans++; cout<<ans%MOD; return 0; }
T2.fseq
求概率,想到分母肯定是C(n+m,n),可是分子呢。。
把+1看成向右走,-1看成向上走,就是在一个N*M的网格图中从原点走到(N,M)的方案数了,这是一个不降路径问题 ,答案为C(n+m,n)
可是这里说任意前缀和不能小于0,所以我们可以形象化这个约束条件,也就是不穿过对角线,神奇的卡特兰数来了。
(C(n+m,n)-C(n+m,n-1))/C(n+m,n)
化简以后就是1-m/(n+1)
代码实现,注意m>n的情况要特判。
#include<iostream> #include<cstdio> using namespace std; int n,m,T; int main(){ cin>>T; while(T--){ cin>>n>>m; if(n<m){ puts("0.000000"); continue; } printf("%.6lf ",1.0-m*1.0/(n+1.0)); } return 0; }
T3.lucky
看起来是数位DP,可以用递归的形式做。
这个问题有明显的子问题性质,对于一个长度为n的数,我们可以分开它的前n-1位和第n位进行考虑,而前n-1位就又是一个子问题了。
考虑计算一个长度为n的数的第x位,它若是等于对称的n-x+1位,那就直接返回。
从中间分开这个序列,前半部分是可以随意填写的,而后半部分就要受到约束(反之亦然成立),约束是一一对应的,所以前半部分是10为底的幂,后半部分是9为底的幂。
预处理形如999...999的数,可以在累计答案时直接加入。
GSH真是太强啦
#include<iostream> #include<cstdio> #define int long long using namespace std; const int MAXLEN=20; int po(int x,int y){ int ret=1; for(int base=x;y;y>>=1,base*=base) if(y&1) ret*=base; return ret; } int a[MAXLEN],res[MAXLEN],bp; int len; int calc(int x){ int tmp=a[x],ans=0ll; if(x==len||(x<bp&&a[x]>a[len-x+1])) tmp--; ans+=tmp*po(10,max(0ll,x-bp))*po(9ll,min(x-1,bp-1)); if(x<bp&&a[x]==a[len-x+1]) return ans; if(x==1) return ans+1ll; ans+=calc(x-1); return ans; } int solve(int x){ len=0; if(x==0) return 0; int ans=0; while(x){ a[++len]=x%10; x/=10; } ans+=res[len-1]; bp=(len/2)+1; ans+=calc(len); return ans; } void prework(){ for(int i=1,tmp=9;i<=18;i++,tmp=tmp*10+9) res[i]=solve(tmp); } signed main(){ int na,nb; cin>>na>>nb; prework(); cout<<solve(nb)-solve(na-1); return 0; }