E. Cow and Treats(数学 方案数)

http://codeforces.com/problemset/problem/1307/E

题意:

n个草一列,m头牛,每头牛有喜欢的草和需要吃这种草的数量。吃饱后会变成路障。

现在选择一些牛,分别从左往右吃和从右往左吃。如果一头牛遇到了路障或者走到尽头还是没有吃够它就会不高兴。

想要选择尽可能多的牛使得他们都高兴,问你最大数量和方案数。

解析:

  • 显然一边不会出现两个相同草的牛。
  • 假设枚举左边第一个牛停下的位置,那么左边每个格子假设会有牛停在这里,那么这个牛已经确定了。
  • 对于不同的牛,方案树之间相乘。
  • 一种牛,先要考虑能不能左右各放一个。假设有x种数量(吃这种草指定数量的牛)可以放两边,y种数量只能放一边。
    • 如果x=0,那么只能放一边,方案数为y
    • 如果x=1且y=0,那么也只能放一边,方案数为2
    • 否则一边x中选一个,另外一边有x-1+y可以选,方案数为x(x-1+y)

代码:

/*
 *  Author : Jk_Chen
 *    Date : 2020-03-05-16.39.33
 */
#include<bits/stdc++.h>
using namespace std;
#define LL long long
#define rep(i,a,b) for(int i=(int)(a);i<=(int)(b);i++)
#define per(i,a,b) for(int i=(int)(a);i>=(int)(b);i--)
#define mmm(a,b) memset(a,b,sizeof(a))
#define pb push_back
#define pill pair<int, int>
#define fi first
#define se second
#define debug(x) cerr<<#x<<" = "<<x<<'\n'
const LL mod=1e9+7;
const int maxn=5e3+9;
const int inf=0x3f3f3f3f;
LL rd(){ LL ans=0; char last=' ',ch=getchar();
    while(!(ch>='0' && ch<='9'))last=ch,ch=getchar();
    while(ch>='0' && ch<='9')ans=ans*10+ch-'0',ch=getchar();
    if(last=='-')ans=-ans; return ans;
}
#define rd rd()
/*_________________________________________________________begin*/

int a[maxn];
int ct[maxn],now[maxn];
bool vis[maxn][maxn];

int main(){
    int n=rd,m=rd;
    rep(i,1,n){
        a[i]=rd;
        ct[a[i]]++;
    }
    rep(i,1,m){
        vis[rd][rd]=1;
    }
    LL ans=0,mx=0;
    rep(i,0,n){
        now[a[i]]++;
        if(i==0||vis[a[i]][now[a[i]]]){
            LL nowans=1,sum=1;
            if(i==0)sum=0;
            rep(j,1,n){
                if(j==a[i]){
                    LL x=0;
                    for(int k=1;k<=ct[j]-now[j];k++){
                        if(vis[j][k]&&k!=now[j]){
                            x++;
                        }
                    }
                    if(x){
                        nowans=nowans*x%mod;
                        sum++;
                    }
                }
                else{
                    LL x=0,y=0;
                    for(int k=1;k<=min(now[j],ct[j]-now[j]);k++){
                        if(vis[j][k]){
                            x++;
                        }
                    }
                    for(int k=min(now[j],ct[j]-now[j])+1;k<=max(now[j],ct[j]-now[j]);k++){
                        if(vis[j][k]){
                            y++;
                        }
                    }
                    if(x==0&&y==0){continue;}
                    if(x==0){
                        nowans=nowans*y%mod;
                        sum++;
                    }
                    else if(x==1&&y==0){
                        sum++;
                        nowans=nowans*2%mod;
                    }
                    else{
                        sum+=2;
                        nowans=nowans*(x*(x-1+y))%mod;
                    }
                }
            }
            if(sum>mx){
                mx=sum;ans=nowans;
            }
            else if(sum==mx){
                ans=(ans+nowans)%mod;
            }
        }
    }

    printf("%lld %lld\n",mx,ans);
    return 0;
}

/*_________________________________________________________end*/

发布了773 篇原创文章 · 获赞 345 · 访问量 20万+

猜你喜欢

转载自blog.csdn.net/jk_chen_acmer/article/details/104728453