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();
	}

}

  

转载于:https://www.cnblogs.com/wzb-hust/p/4770626.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值