lightoj 1095 - Arrange the Numbers(dp+组合数)

题目链接:http://www.lightoj.com/volume_showproblem.php?problem=1095

题解:其实是一道简单的组合数只要推导一下错排就行了。在这里就推导一下错排

dp[i]=(i-1)*dp[i-2](表示新加的那个数放到i-1中的某一个位置然后那个被放位置的数放在i这个位置就是i-2的错排)+(i-1)*dp[i-1](表示新加的那个数放到i-1中的某一个位置然后用那个位置被占的数代替i这个位置的数就是i-1的错排)

#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
#define mod 1000000007
using namespace std;
typedef long long ll;
const int M = 1e3 + 10;
ll dp[M];
ll up[M] , down[M];
ll inv(ll a) {
    return a == 1 ? 1 : (ll)(mod - mod / a) * inv(mod % a) % mod;
}
void fk() {
    dp[0] = 1 , dp[1] = 0 , dp[2] = 1;
    for(int i = 3 ; i < M ; i++) dp[i] = (i - 1) * ((dp[i - 1] + dp[i - 2]) % mod) , dp[i] %= mod;
}
ll C(ll n , ll m)
{
    if(m < 0)return 0;
    if(n < m)return 0;
    if(m > n-m) m = n-m;
    ll up = 1, down = 1;
    for(ll i = 0 ; i < m ; i++){
        up = up * (n-i) % mod;
        down = down * (i+1) % mod;
    }
    return up * inv(down) % mod;
}
int main() {
    fk();
    int t , Case = 0;
    scanf("%d" , &t);
    while(t--) {
        int n , m , k;
        scanf("%d%d%d" , &n , &m , &k);
        ll ans = 0;
        ll gg = C(m , k);
        up[0] = 1 , down[0] = 1;
        for(int i = 1 ; i <= (n - m) / 2 ; i++) up[i] = up[i - 1] * ((n - m) - i + 1) % mod , down[i] = down[i - 1] * i % mod;
        for(int i = (n - m) / 2 + 1 ; i <= (n - m) ; i++) up[i] = up[(n - m) - i] , down[i] = down[(n - m) - i];
        for(int i = n - k ; i >= (m - k) ; i--) {
            ans += dp[i] * (up[n - k - i] * (inv(down[n - k - i]) % mod) % mod);
            ans %= mod;
        }
        ans *= gg;
        ans %= mod;
        printf("Case %d: %lld\n" , ++Case , (ans + mod) % mod);
    }
    return 0;
}
时间: 2024-11-03 05:34:44

lightoj 1095 - Arrange the Numbers(dp+组合数)的相关文章

lightoj 1095 - Arrange the Numbers (错排数)

题意: 求n个数的排列,前m个中有k个在自己的位置上的方法数. 思路: 设D[n]为n个元素的错排数. 于是我们有D[1] = 0 D[2] = 1: D[n] = (D[n-1] + D[n-2]) * (i-1) 考虑问题本身,我们首先从前m个数选k个数不动.即C(m,k).对于没有选的前m中的m-k个数肯定是参与了错排,而后面n-m个数中参加错排的个数不定,所以我们枚举一个后面n-m个数中选出i(0 <= i <= n - m)个数有没有参与错排.总共就有n-k-i参与了错排. 综上所述

LightOJ - 1095 - Arrange the Numbers(错排)

链接: https://vjudge.net/problem/LightOJ-1095 题意: Consider this sequence {1, 2, 3 ... N}, as an initial sequence of first N natural numbers. You can rearrange this sequence in many ways. There will be a total of N! arrangements. You have to calculate t

Light oj 1095 - Arrange the Numbers (组合数学+递推)

题目链接:http://www.lightoj.com/volume_showproblem.php?problem=1095 题意: 给你包含1~n的排列,初始位置1,2,3...,n,问你刚好固定前m个数中的k个数的位置,问你有多少中排列方案.(比如5 3 2有1 4 3 2 5这种方案,1和3固定了) 思路: 前m个取k个就是C(m, k)个方案.然后就是类似错排的思想,设dp[i]为i个数在初始位置各不相同.其中的组合数用逆元算出. ans = dp[m - k] * C(n - m,

LightOJ - 1246 Colorful Board(DP+组合数)

http://lightoj.com/volume_showproblem.php?problem=1246 题意 有个(M+1)*(N+1)的棋盘,用k种颜色给它涂色,要求曼哈顿距离为奇数的格子之间不能涂相同的颜色,每个格子都必须有颜色,问可行的方案数. 分析 经一波分析,根据曼哈顿距离为奇数这一信息,可以将棋盘分为两部分,也就是相邻格子不能有相同颜色.一种颜色只能在一个部分中出现.现在考虑对一个部分的格子操作, dp[i][j]表示i个格子选择用了j种颜色的方案数,于是可以得到这样的递推式:

Codeforces 747F Igor and Interesting Numbers DP 组合数

题意:给你一个数n和t,问字母出现次数不超过t,第n小的16进制数是多少. 思路:容易联想到数位DP, 然而并不是...我们需要知道有多少位,在知道有多少位之后,用试填法找出答案.我们设dp[i][j]为考虑前i种字母,已经占了j个位置的方案数.那么dp[i][j] += dp[i - 1][j - k] * C[len - j + k][k],k的范围为[0, limit[k]].意思是我们暴力枚举第i个字母放多少个,然后排列组合. 这个题有一个细节需要注意,因为最高为一定不为0,所以我们试填

LightOJ 1095 Arrange the Numbers-容斥

给出n,m,k,求1~n中前m个正好有k个在原来位置的种数(i在第i个位置) 做法:容斥,先选出k个放到原来位置,然后剩下m-k个不能放到原来位置的,用0个放到原来位置的,有C(m-k,0)*(n-k)!种 - 1个放原来位置的,有C(m-k,1)*(n-k-1)!种+...-... 1 #include <bits/stdc++.h> 2 using namespace std; 3 typedef long long LL; 4 const int N=1e3+10; 5 const in

Light OJ 1095 Arrange the Numbers

给定n,m,k,要求在n的全排列中,前m个数字中恰好有k个位置不变,有几种方案?首先,前m个中k个不变,那就是C(m,k),然后利用容斥原理可得 ans=ΣC(m,k)*(-1)^i*C(m-k,i)*(n-k-i)! (0<=i<=m-k) 1 #include<algorithm> 2 #include<cstdio> 3 #include<cmath> 4 #include<cstring> 5 #include<iostream&g

hdu 4945 2048 (dp+组合数)

2048 Time Limit: 3000/1500 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 840    Accepted Submission(s): 199 Problem Description Teacher Mai is addicted to game 2048. But finally he finds it's too hard to get 2048.

UVA 11481 - Arrange the Numbers(组合数学)

题目链接:11481 - Arrange the Numbers 题意:序列1-n,进行重排,问最后前m个中有k个仍然位置不变的情况数 思路:之前写过UVA 580, n个数重排,要求每个位置都不同的情况的题目,递推式为dp[i] = (i - 1) * (dp[i - 1] + dp[i - 2]) 利用这个,这题只要: k个位置C(m, k) * sum(C[n - m][i] (后面n-m个选出i个对应正确匹配) * dp[n - k - i](其余位置全都错排)} 这便是总情况数 代码: