10.9 下午 考试

T1

f(i)表示不和法数大于i个的数量

$$f(i)=C_n^iC_{m-i*k-1}^{n-1}$$

首先n>m||K*n<m一定不合法

先不考虑<K的情况,那就相当于给m个果子,用n个篮子把他们装起来

用挡板法易知

$$ans=C_{m+n-1}^{n-1}$$

即给m个果子中间再加上n-1个挡板的位置,在选n-1个

那考虑必须放一个的情况,只要预先把m  -n,相当于每个篮子先放一个

那考虑不合法数>=i个,只需要预先给i个放K个,那这i个一定不合法

但是不保证其他的合法,也不保证这i个不合法的果子数一定是K+1个

所以要用到容斥

 

这种我们确定了i个不合法的最低高度,但是同一个状态会被像上图一样,被枚举多次

所以要容斥

 

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <cmath>
#include <algorithm>
#define mem(a,b) memset(a,b,sizeof(a))
#define ll long long
using namespace std;
const int mod=998244353;
const int N=10000066;

ll mi(ll a,ll ci)
{
    ll ans=1;
    while(ci)
    {
        if(ci&1)
            ans=ans*a%mod;
        a=a*a%mod;
        ci>>=1;
    }
    return ans;
}

ll jie[N],jieni[N];

void chu()
{
    jie[0]=1;
    for(int i=1;i<N;++i)
        jie[i]=jie[i-1]*i%mod;
    jieni[N-1]=mi(jie[N-1],mod-2)%mod;
    for(int i=N-2;i>=1;--i)
        jieni[i]=jieni[i+1]*(ll)(i+1)%mod;
    jieni[0]=1;
}

ll n,m,K;

inline ll C(ll n,ll m)
{
    if(n<0||m<0)
        return 0;
    if(n<m)
        return 0;
    return jie[n]*jieni[m]%mod*jieni[n-m]%mod;
}

int main(){

    //freopen("T1.in","r",stdin);

    chu();

    scanf("%lld%lld%lld",&n,&m,&K);
    if(n>m)
    {
        cout<<0;
        return 0;
    }
    ll ans=0;
    for(ll i=0;i<=m;++i)
        ans=(ans+C(n,i)*C(m-i*K-1,n-1)%mod*((i&1)?-1:1)+mod)%mod;
    cout<<ans%mod;
}
T1

 

 

T2

仔细想一想就会发现

一条链上、一个环上只能放一个

如果有多条链、多个环组合在一起,ans还是最长链的长度

那只需要tarjan缩个点,再求个最长链即可

 

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <cmath>
#include <algorithm>
#define mem(a,b) memset(a,b,sizeof(a))
#define ll long long
#define dd double
using namespace std;
inline int read()
{
    char q=getchar();int ans=0;
    while(q<'0'||q>'9')q=getchar();
    while(q>='0'&&q<='9'){ans=ans*10+q-'0';q=getchar();}
    return ans;
}
const int N=1000006;
struct son
{
    int v,next;
};

struct TTT
{
    son a1[N*3];
    int first[N*3],e;
    void clear()
    {
        mem(a1,0);mem(first,-1);e=0;
    }
    void addbian(int u,int v)
    {
        a1[e].v=v;
        a1[e].next=first[u];
        first[u]=e++;
    }
}h[2];

int n,m;

int dfn[N],low[N],now;
int zhan[N*5],he;
bool flag[N];
int dui[N],con,sun[N];

inline void tarjan(int x)
{
    low[x]=dfn[x]=++now;
    zhan[++he]=x;flag[x]=1;
    int temp;
    for(int i=h[0].first[x];i!=-1;i=h[0].a1[i].next)
    {
        temp=h[0].a1[i].v;
        //if(flag[temp])
        //    continue;
        if(dfn[temp]==-1)
        {
            tarjan(temp);
            if(low[x]>low[temp])
              low[x]=low[temp];
            //low[x]=min(low[x],low[temp]);
        }
        else
            if(flag[temp])
            {
                if(low[x]>dfn[temp])
                    low[x]=dfn[temp];
                //low[x]=min(low[x],dfn[temp]);
            }
    }
    if(dfn[x]==low[x])
    {
        ++con;
        while(1)
        {
            temp=zhan[he--];
            flag[temp]=0;
            dui[temp]=con;
            ++sun[con];
            if(temp==x)
                break;
        }
    }
}

void chu()
{
    for(int i=1;i<=n;++i)
        if(dfn[i]==-1)
            tarjan(i);

    for(int i=1;i<=n;++i)
    {
        int temp;
        for(int j=h[0].first[i];j!=-1;j=h[0].a1[j].next)
        {
            temp=h[0].a1[j].v;
            if(dui[i]!=dui[temp])
                h[1].addbian(dui[i],dui[temp]);
        }
    }
}

int mx[N];

void dfs(int x)
{
    flag[x]=1;
    int temp;
    mx[x]=sun[x];
    for(int i=h[1].first[x];i!=-1;i=h[1].a1[i].next)
    {
        temp=h[1].a1[i].v;
        if(flag[temp])
        {
            if(mx[x]<sun[x]+mx[temp])
                mx[x]=sun[x]+mx[temp];
            continue;
        }
        dfs(temp);
        if(mx[x]<sun[x]+mx[temp])
            mx[x]=sun[x]+mx[temp];
    }
}

int work()
{
    mem(flag,0);
    for(int i=1;i<=con;++i)
        if(!flag[i])
            dfs(i);
    int ans=0;
    for(int i=1;i<=con;++i)
        if(ans<mx[i])
            ans=mx[i];
    return ans;
}

int main(){

    //freopen("T2.in","r",stdin);

    //freopen("bomb.in","r",stdin);

    mem(dfn,-1);
    h[0].clear();
    h[1].clear();

    n=read();m=read();
    int tin1,tin2;
    for(int i=1;i<=m;++i)
    {
        tin1=read();tin2=read();
        h[0].addbian(tin1,tin2);
    }
    chu();

    /*printf("
");
    for(int i=1;i<=n;++i)
        printf("%d ",dui[i]);
    printf("
");*/

    cout<<work();
}
T2

 

 

然后T3还不会呢...

 

原文地址:https://www.cnblogs.com/A-LEAF/p/7643811.html