Gym 100345B Signed Derangements

Problem B. Signed Derangements Input file: derangements.in Output file: derangements.out Time limit: 1 second Memory limit: 256 megabytes Signed permutation of size n is an ordered set of n numbers ranging from −n to n except 0, where absolute values of any two numbers are different. An example of a signed permutation is ?4, −2, 3, −5, −1?. Clearly, there are 2nn! signed permutations of size n. A signed permutation ?a1, a2, . . . , an? is called a signed derangmenent if ai ?= i for all i. For example, ?4, −2, 3, −5, −1? is not a signed derangement, but ?4, −2, −3, −5, −1? is. Given n, find the number of signed derangements of size n. Input Input file contains one integer number n (1 ≤ n ≤ 200). Output Output one integer number — the number of signed derangements of size n. Example derangements.in derangements.out 2 5 The following signed 2-permutations are signed derangements: ?2, 1?, ?2, −1?, ?−2, 1?, ?−1, −2?, and ?−2, −1?.

容斥原理

import java.util.*;
import java.io.*;
import java.math.*;
public class Main {

	/**
	 * @param args
	 */
	public static void main(String[] args) throws FileNotFoundException
	{
		// TODO Auto-generated method stub
		Scanner cin = new Scanner (new File("derangements.in"));
		PrintWriter cout = new PrintWriter(new File("derangements.out"));
		//Scanner cin = new Scanner (System.in);
		BigInteger [][] C = new BigInteger [210][210];
		BigInteger [] N = new BigInteger [210];
		BigInteger [] Two = new BigInteger [210];
		BigInteger two;
		two=BigInteger.ONE;
		two=two.add(two);
		C[0][0]=BigInteger.ONE;
		for (int i=1;i<=200;i++)
		{
			C[i][0]=C[i][i]=BigInteger.ONE;
			for (int j=1;j<i;j++) {
				C[i][j] = BigInteger.ZERO;
				C[i][j]=C[i][j].add(C[i-1][j-1]);
				C[i][j]=C[i][j].add(C[i-1][j]);
			}
		}
		N[0] = BigInteger.ONE;
		for (int i=1;i<=200;i++) {
			BigInteger tp = new BigInteger(String.valueOf(i));
			N[i] = N[i-1].multiply(tp);
		}
		Two[0] = BigInteger.ONE;
		for (int i=1;i<=200;i++) {
			Two[i] = Two[i-1].multiply(two);
		}
		int n;
		n = cin.nextInt();
		BigInteger ans = BigInteger.ZERO;
		ans=Two[n].multiply(N[n]);
		int cur=0;
		for (int i=1;i<=n;i++){
			if (cur==0) {
				BigInteger tp = C[n][i].multiply(Two[n-i]);
				tp=tp.multiply(N[n-i]);
				ans=ans.subtract(tp);
				cur=1-cur;
			}
			else {
				BigInteger tp = C[n][i].multiply(Two[n-i]);
				tp=tp.multiply(N[n-i]);
				ans=ans.add(tp);
				cur=1-cur;
			}
		}
		cout.println(ans);
		//System.out.println(ans);
		cin.close();
		cout.close();
	}

}

  

时间: 2024-11-06 09:30:47

Gym 100345B Signed Derangements的相关文章

Codeforces Gym 101190M Mole Tunnels - 费用流

题目传送门 传送门 题目大意 $m$只鼹鼠有$n$个巢穴,$n - 1$条长度为$1$的通道将它们连通且第$i(i > 1)$个巢穴与第$\left\lfloor \frac{i}{2}\right\rfloor$个巢穴连通.第$i$个巢穴在最终时允许$c_i$只醒来的鼹鼠最终停留在这.已知第$i$只鼹鼠在第$p_i$个巢穴睡觉.要求求出对于每个满足$1 \leqslant k \leqslant n$的$k$,如果前$k$只鼹鼠醒来,最小的移动距离的总和. 考虑费用流的建图和暴力做法,把原图的

CodeForces Gym 100935D Enormous Carpet 快速幂取模

Enormous Carpet Time Limit:2000MS     Memory Limit:65536KB     64bit IO Format:%I64d & %I64u Gym 100935D Description standard input/outputStatements Ameer is an upcoming and pretty talented problem solver who loves to solve problems using computers.

B - Average Gym - 101161B 组合数学

http://codeforces.com/gym/101161/attachments 今天被卡常了,其实是自己对组合数技巧研究的不够. 如果是n, m <= 1e5的,然后取模是质数,那么可以用费马小定理. 如果n, m都比较小,那么其实是直接杨辉三角.不用逆元那些. 这题的思路是,枚举每一一个ave,然后总和就是n * ave 相当于方程  x1 + x2 + .... + xn = n * ave中,在0 <= x[i] <= full的情况下,不同解的个数中,使得x[i] ==

Codeforces Gym 100269 Dwarf Tower (最短路)

题目连接: http://codeforces.com/gym/100269/attachments Description Little Vasya is playing a new game named "Dwarf Tower". In this game there are n different items,which you can put on your dwarf character. Items are numbered from 1 to n. Vasya want

CodeForces Gym 101063C 二进制压缩

http://codeforces.com/gym/101063/problem/C 给n个人,m样物品,每个人可以从物品中选择几样.两人选择物品的交集元素个数比上并集元素个数如果大于某个比例即可将两人配对.求配对数. n的范围是1e5,直接比较所有人的选择会TLE,应该将所有选择物品的情况用二进制压缩,m最大是10,情况数目小于2048,可以接受.注意配对总数范围应为long long. #define _CRT_SECURE_NO_WARNINGS #include <stdio.h> i

Gym 101246H ``North-East&#39;&#39;(LIS)

http://codeforces.com/gym/101246/problem/H 题意: 给出n个点的坐标,现在有一个乐队,他可以从任一点出发,但是只能往右上方走(包括右方和上方),要经过尽量多的点.输出它可能经过的点和一定会经过的点. 思路: 分析一下第一个案例,在坐标图上画出来,可以发现,他最多可以经过4个点,有两种方法可以走. 观察一下,就可以发现这道题目就是要我们求一个LIS. 首先,对输入数据排一下顺序,x小的排前,相等时则将y大的优先排前面. 用二分法求LIS,这样在d数组中就可

Gym 100712I Bahosain and Digits(开关翻转问题)

http://codeforces.com/gym/100712/attachments 题意: 给出一串数字,每次选择连续的k个数字加上任意数(超过10就取余),最后要使得所有数字都相等,求最大的k. 思路: 开关翻转问题. 算法具体可以参考<挑战程序竞赛>常用技巧篇. 这道题目就是在枚举k的同时再枚举一下最后要转换成的数字即可. 1 #include<iostream> 2 #include<algorithm> 3 #include<cstring>

很好的脑洞题:dfs+暴力 Gym - 101128A Promotions

http://codeforces.com/gym/101128 题目大意:给你一个a,b,e,p.有e个点,p条有向边,每条边为(x,y),表示x->y,每次我们都取出一个入度为0的,并且一次性取出来的个数为a(或b).当然,取出来的种类可能有很多种(即一个集合),问,这个集合中有多少个数字是相同的. 第一个输出集合长度为a的,第二个输出集合长度为b的,第三个输出无论如何都无法被取出的个数. 思路:建立正向图和反向图. 定义pair<int, int> interval[i] 表示第i

【树状数组】Gym - 101147J - Whistle&#39;s New Car

题意就是对每个点i,统计在其子树内(不含自身),且depj-depi<=xj的点有多少个. 把点分别按照dep-x和dep进行排序,离线处理, 每次把dep-x小于等于当前dep值的点插入树状数组,就变成了询问dfs序在一个区间内的点有多少个,可以用树状数组轻松解决. #include<cstdio> #include<algorithm> #include<cstring> using namespace std; int f,C; void R(int &am