2017.10.11 Problem c 失败总结

来源:互联网 发布:php prematch 编辑:程序博客网 时间:2024/05/18 22:41

一开始就想偏了。。

首先计数题 30s + n<=300显然是让你n^3 dp的

先从手玩开始考虑

注意到从大到小出现的数字个数是可以判断有无解的

,,然后可以画出一些区间的条件  如(>=8的数最多有几个、、 >=4的最多有几个)  

按序列从前往后dp  前面每一个人的安排是可以离散的,但就算离散了状态也炸了,  按照条件存信息至少也是n^4的dp,  所以就不可做了

这是因为这样做把所有状态合到了一起   忽略了一个优化点:后面的信息的影响

由于前后信息一起影响,所以可以考虑把影响分类,,之后会发现顺序是没用的,所以可以提取离散

同时~n>=的约束可以化为~1<=的约束

所以就可以在离散之后的每一个数上做选择

所以选择的方案也都是离散的,适当枚举


注: YES 0 和NO 不一样!


码:

#include<iostream>#include<cstdio>using namespace std;int T,n,m,M,f[305][305],c[305][305],i,j,k,he[305],yq[305],x;int main(){scanf("%d",&T);while(T--){scanf("%d%d%d",&n,&m,&M);c[0][0]=1;for(i=1;i<=n;i++){yq[i]=0;c[i][0]=1;for(j=1;j<=n;j++)c[i][j]=1ll*(c[i-1][j-1]+c[i-1][j])%M,f[i][j]=0;    }    bool bx=0;    int sum=0;for(i=1;i<=m;i++){scanf("%d%d",&j,&x);yq[x]++;}   for(i=n;i>=1;i--)   {   sum+=yq[i];   if(sum>n-i+1)bx=1;   }if(bx==1){printf("NO\n");continue;}for(i=1;i<=n;i++){he[i]=he[i-1]+yq[i];}f[0][0]=1;for(i=1;i<=n;i++)//对于i的限制条件 {for(j=max(he[i-1],i-1);j<=n;j++)//上一个状态有j个人已确定 {//                      ↓后面必备 for(k=yq[i];k+j+    he[n]-he[i]    <=n;k++)//合法的k个人选i      //                                 n-j:这+后   he-he:i及以后 f[i][j+k]=(f[i][j+k]+1ll*f[i-1][j]*c[n-j-he[n]+he[i-1]][k-yq[i]]%M)%M;}}printf("YES %d\n",f[n][n]);}}


%题解%到一句话:


OI题有三种  从一般到特殊,从暴力到优化,换角度思考 WerkeyTom_FTD 

这神题三种都是。。



原创粉丝点击