【NOIP2017提高A组集训10.22】友谊

来源:互联网 发布:域名纠纷解决方式 编辑:程序博客网 时间:2024/04/29 20:51

Description

Flowey 是一朵能够通过友谊颗粒传播LOVE 的小花.它的友谊颗粒分为两种,
圆粒的和皱粒的,它们依次排列组成了一个长度为2m 的序列.对于一个友谊颗
粒的序列,如果存在1<=i

Solution

这道题60分很好打,设f[i][j][k]为做到第i个,偶数的圆粒和皱粒的个数,然后转移,注意要看到只有前偶后奇才能转移就很简单了。
我们发现,最麻烦的东西就是上面的限制。
要要求数量不超过2n,那么我们就在前面强制放n个偶数(圆粒+皱粒=n),然后只要后面失配的奇数可以被前面的这个n匹配完,那么就合法。
因为我们是一奇一偶的加进来的,所以我们偶数的个数一定不会减少(进来一对奇偶,匹不匹配成功偶数总数都为n),那么就是圆粒还是皱粒的问题了,设f[i][j]表示做到第i个偶数圆粒为j个,那么偶数皱粒为n-j个,所以就可以像60分一样强行转移。
但是我们发现会算重,有很多情况都会算重。
但是我们发现当j=0的时候是不会算重的,因为这时的序列是唯一确定的,所以我们还要多记录一维表示是否已经达到过0。
但是我们可以发现第一个奇数是不会被前面的偶数匹配到的,所以这个奇数和另一个偶数的颜色随意,最后答案*4

Code

#include<iostream>#include<stdio.h>#include<string.h>#include<algorithm>#include<math.h>#define fo(i,a,b) for(i=a;i<=b;i++)#define min(a,b) (a<b?a:b)using namespace std;typedef long long ll;const int maxn=3007;ll i,j,k,l,t,n,m,ans,mo,u,v;ll f[maxn][maxn][2];int main(){    freopen("friend.in","r",stdin);    freopen("friend.out","w",stdout);    scanf("%lld%lld%lld",&n,&m,&mo);n--,m--;    fo(i,1,n)f[0][i][0]=1;f[0][0][1]=1;    fo(i,0,m-1){        fo(j,0,n){            f[i+1][j][0]=(f[i+1][j][0]+2*f[i][j][0])%mo;            f[i+1][j][1]=(f[i+1][j][1]+2*f[i][j][1])%mo;            f[i+1][j+1][0]=(f[i+1][j+1][0]+f[i][j][0])%mo;            f[i+1][j+1][1]=(f[i+1][j+1][1]+f[i][j][1])%mo;            if(j){                if(j==1)f[i+1][j-1][1]=(f[i+1][j-1][1]+f[i][j][1]+                f[i][j][0])%mo;                else f[i+1][j-1][1]=(f[i+1][j-1][1]+f[i][j][1])%mo                ,f[i+1][j-1][0]=(f[i+1][j-1][0]+f[i][j][0])%mo;            }        }    }    fo(i,0,n)ans=(ans+f[m][i][1])%mo;    printf("%lld\n",ans*4%mo);}
阅读全文
1 0
原创粉丝点击