zoukankan      html  css  js  c++  java
  • 【JZOJ3059】【NOIP2012模拟10.26】雕塑【数论】【容斥】

    题目大意:

    题目链接:https://jzoj.net/senior/#main/show/3059
    n×nn imes nmm个障碍网格中选择nn个格子,使得任意两个格子不在同一行、同一列的方案数。


    思路:

    由于mm只有1010,可以考虑用总方案数-放在障碍上的方案数。
    总方案数很明显是n!n!
    因为第一行有nn个格子可以选,选择其中一个后,第二行就有n1n-1个格子可选,第三行就有n2n-2个可选,一直到最后一行只有11个可选。总方案数就是n×(n1)×...×1=n!n imes (n-1) imes ... imes 1=n!
    然后我们会发现总方案数里面包含了选择11个障碍的方案数。所以我们再减去选择11个的方案数。此时我们会发现,总方案数里面包含了选择22个方案数,减去选择一个的方案数后,减去的也包含了选择22个障碍的方案数。相抵消,就等于没有减去选择22个障碍的方案数。于是我们就要减去选择22个的方案数。然后加上选择33个,减去选择44个。。。
    用人话说,设sis_i表示在n×nn imes n网格中选择nn个格子,其中有ii个格子是障碍的情况数量。那么答案就是
    {n!s1+s2s3+s4...sn1+sn(n%2==0)n!s1+s2s3+s4...+sn1sn(n%2==1)left{egin{matrix}n!-s_1+s_2-s_3+s_4-...-s_{n-1}+s_n(n\%2==0) \n!-s_1+s_2-s_3+s_4-...+s_{n-1}-s_n(n\%2==1)end{matrix} ight.
    那么如何求si?s_i?
    很明显,si=s_i=选择ii个障碍的方案数× imes选择mim-i个非障碍的方案数。
    选择ii个障碍的方案数可以用搜索求。因为mm只有1010,可以2m2^m判断是否选择则个障碍。
    那么选择mim-i个非障碍的方案数其实就是要我们求在(mi)×(mi)(m-i) imes(m-i)的格子里选择mm个格子的方案数,自然就是m!m!了。
    0200sim 20的阶乘要提前预处理,时间复杂度O(m×2m)O(m imes 2^m)


    代码:

    #include <cstdio>
    #include <iostream>
    using namespace std;
    typedef long long ll;
    
    int n,m,x[15],y[15];
    ll ans,num[25],s;
    bool used[3][25];
    
    void dfs(int i,int cnt,int sum)
    //i表示处理到第i个障碍,cnt表示选择了多少个障碍,sum表示需要选择的总障碍数
    {
        if (cnt==sum)  //选择完毕
        {
            s++;  //方案数
            return;
        }
        if (i>m) return;
        if (!used[1][x[i]]&&!used[2][y[i]])  //这一行和这一列都没有被选择
        {
            used[1][x[i]]=used[2][y[i]]=1;
            dfs(i+1,cnt+1,sum);
            used[1][x[i]]=used[2][y[i]]=0;
        }
        dfs(i+1,cnt,sum);
    }
    
    int main()
    {
        scanf("%d%d",&n,&m);
        for (int i=1;i<=m;i++)
            scanf("%d%d",&x[i],&y[i]);
        num[0]=1;
        for (int i=1;i<=n;i++)  //预处理阶乘
            num[i]=i*num[i-1];
        ans=num[n];
        for (int i=1;i<=m;i++)
        {
            s=0;
            dfs(1,0,i);
            if (!s) break;
            if (i&1) ans-=s*num[n-i];
                else ans+=s*num[n-i]; 
        }
        printf("%lld
    ",ans);
        return 0;
    }
    
  • 相关阅读:
    Apache服务器的安装与配置
    改变HTML下拉框选项的方法
    Struts2性能调优拦截器
    上传文件到服务器的Linux命令
    Strut2判断是否是AJAX调用
    MySQL自动关闭连接导致DBCP报错
    Tomcat6添加MySQL的JNDI数据源
    Linux查找命令
    SqlServer与Oracle的分页(收集整理) 中庸
    struts2入门
  • 原文地址:https://www.cnblogs.com/hello-tomorrow/p/11998409.html
Copyright © 2011-2022 走看看