【容斥+大数】SGU 476 Coach's Trouble

通道

题意:有3*n个人,分成n组,每组三个人。给出k个三元组,这三个人不可组队,问最后可以组队的总方案数

思路:

当k=0时,有(C[3*n][3]*C[3*n-3][3]*……*C[3][3])/n!种方案,展开以后可以得到dp[n]=(3*n)!/n!/6^n。

显然可以写成递推式:dp[n]=dp[n-1]*(3*n-1)*(3*n-2)/2。

那么容斥一下,答案=总方案数-至少含一个禁止组合的+至少含两个禁止组合的-……

二进制暴力TLE了。DFS的话会有很多剪枝,当前几个已经出现冲突,自然不会再往后面搜了

代码:

import java.util.*;
import java.math.*;

public class Solution {
    static int group[][] = new int[25][3];
    static int cnt[] = new int[25];
    static boolean vis[] = new boolean[3001];
    static int n, k, depth;

    static void Init() {
        for (int i = 0; i < 25; i++)
            cnt[i] = 0;
        for (int i = 0; i < 3001; i++)
            vis[i] = false;
    }

    static void DFS(int index, int now) {
        if (now == depth) {
            if (depth % 2 == 1)
                cnt[depth]++;
            else
                cnt[depth]--;
        } else {
            for (int i = index; i < k; i++) {
                if (vis[group[i][0]] == false && vis[group[i][1]] == false
                        && vis[group[i][2]] == false) {
                    vis[group[i][0]] = vis[group[i][1]] = vis[group[i][2]] = true;
                    DFS(i + 1, now + 1);
                    vis[group[i][0]] = vis[group[i][1]] = vis[group[i][2]] = false;
                }
            }
        }
    }

    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        BigInteger dp[] = new BigInteger[1001];
        BigInteger res;
        dp[0] = dp[1] = BigInteger.ONE;
        for (int i = 2; i < 1001; i++)
            dp[i] = dp[i - 1].multiply(BigInteger.valueOf(3 * i - 1))
                    .multiply(BigInteger.valueOf(3 * i - 2))
                    .divide(BigInteger.valueOf(2));
        while (in.hasNext()) {
            Init();
            n = in.nextInt();
            k = in.nextInt();
            for (int i = 0; i < k; i++)
                for (int j = 0; j < 3; j++)
                    group[i][j] = in.nextInt();
            for (depth = 1; depth <= k; depth++)
                DFS(0, 0);
            res = BigInteger.ZERO;
            for (int i = 1; i <= k; i++)
                if (cnt[i] != 0)
                    res = res.add(dp[n - i].multiply(BigInteger.valueOf(cnt[i])));
            System.out.println(dp[n].subtract(res));
        }
    }
}

【容斥+大数】SGU 476 Coach's Trouble

时间: 2024-10-09 11:21:17

【容斥+大数】SGU 476 Coach's Trouble的相关文章

POJ 1091 跳蚤(分解质因数 + 容斥 + 大数)

跳蚤 Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 8910   Accepted: 2676 Description Z城市居住着很多只跳蚤.在Z城市周六生活频道有一个娱乐节目.一只跳蚤将被请上一个高空钢丝的正中央.钢丝很长,可以看作是无限长.节目主持人会给该跳蚤发一张卡片.卡片上写有N+1个自然数.其中最后一个是M,而前N个数都不超过M,卡片上允许有相同的数字.跳蚤每次可以从卡片上任意选择一个自然数S,然后向左,或向

HDU 4059 The Boss on Mars-矩阵+容斥

错了29遍,终成正果..... 根据题意,很容易的可以想到容斥. 然后的问题就是如何求 sum(n)=1^4+2^4+3^4+....+n^4; 有三种道路: 很显然:1^4+2^4+3^4+....+n^4=(n^5)/5+(n^4)/2+(n^3)/3-n/30: 则1,用java的大数去敲这个的代码. 2,用c++敲,但是用到分数取模,求逆元. 3,用c++敲,但是不用这个公式,用矩阵去构造sum(n). 我用的是第三种.但是第三种有的缺陷,就是时间复杂度有点高. 接下来的问题就是如何优化

POJ2103 Jackpot(容斥+高精度)

Jackpot Time Limit: 20000MS   Memory Limit: 64000K Total Submissions: 1044   Accepted: 216 Case Time Limit: 2000MS Description The Great Dodgers company has recently developed a brand-new playing machine. You put a coin into the machine and pull the

hdu5794 A Simple Chess 容斥+Lucas 从(1,1)开始出发,每一步从(x1,y1)到达(x2,y2)满足(x2?x1)^2+(y2?y1)^2=5, x2&gt;x1,y2&gt;y1; 其实就是走日字。而且是往(n,m)方向走的日字。还有r个障碍物,障碍物不可以到达。求(1,1)到(n,m)的路径条数。

A Simple Chess Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 2597    Accepted Submission(s): 691 Problem Description There is a n×m board, a chess want to go to the position (n,m) from the pos

HDU 4790:Just Random(容斥)

Just Random Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 3932 Accepted Submission(s): 1276 Problem Description Coach Pang and Uncle Yang both love numbers. Every morning they play a game with n

POJ 2773 Happy 2006 二分+容斥(入门

题目链接:点击打开链接 题意: 输入n ,k 求与n互质的第k个数(这个数可能>n) 思路: solve(mid)表示[1,mid]中有多少个和n互质,然后二分一下最小的mid 使得互质个数==k solve(x) 实现: 与n互质的个数=所有数-与n不互质的数=所有数-(与n有一个因子-与n有2个因子的+与n有3个因子的) 状压n的因子个数,然后根据上面的公式容斥得到. #include <stdio.h> #include <iostream> #include <

hdu1695(莫比乌斯)或欧拉函数+容斥

题意:求1-b和1-d之内各选一个数组成数对,问最大公约数为k的数对有多少个,数对是有序的.(b,d,k<=100000) 解法1: 这个可以简化成1-b/k 和1-d/k 的互质有序数对的个数.假设b=b/k,d=d/k,b<=d.欧拉函数可以算出1-b与1-b之内的互质对数,然后在b+1到d的数i,求每个i在1-b之间有多少互质的数.解法是容斥,getans函数参数的意义:1-tool中含有rem位置之后的i的质因子的数的个数. 在 for(int j=rem;j<=factor[i

HDU 4135 Co-prime(容斥+数论)

Co-prime Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 5526    Accepted Submission(s): 2209 Problem Description Given a number N, you are asked to count the number of integers between A and B

hdu 5664 Lady CA and the graph(树的点分治+容斥)

题意: 给你一个有n个点的树,给定根,叫你找第k大的特殊链 .特殊的链的定义:u,v之间的路径,经过题给的根节点. 题解:(来自BC官方题解) 对于求第k大的问题,我们可以通过在外层套一个二分,将其转化为求不小于mid的有多少个的问题. 接下来我们讨论如何求树上有多少条折链的长度不小于k. 我们考虑常规的点分治(对于重心,求出其到其他点的距离,排序+单调队列),时间复杂度为O(nlog^2n),但是这只能求出普通链的数量. 我们考虑将不属于折链的链容斥掉.也即,我们需要求出有多少条长度不小于mi