zoukankan      html  css  js  c++  java
  • bzoj 4465: [Jsoi2013]游戏中的学问

    4465: [Jsoi2013]游戏中的学问

    Time Limit: 10 Sec  Memory Limit: 256 MB
    Submit: 121  Solved: 59
    [Submit][Status][Discuss]

    Description

    大家应该都见过很多人手拉手围着篝火跳舞的场景吧?一般情况下,大家手
    拉手跳舞总是会围成一个大圈,每个人的左手拉着旁边朋友的右手,右手拉着另
    一侧朋友的左手。
    不过,如果每一个人都随机的拉住两个不同人的手,然后再慢慢散开,事情
    就变得有趣多了——此时大家依旧会形成圈,不过却可能会形成多个独立的圈。
    当然这里我们依然要求一个人的右手只能拉另一个人的左手,反之亦然。
    班里一共有N个同学,由1到N编号。Will想知道,究竟有多少种本质不
    同的拉手方案,使得最终大家散开后恰好形成k个圈呢?
    给定两种方案,若存在一个人和他的一只手,满足在这两种方案中,拉着这
    只手的人的编号不同,则这两种方案本质不同。

    Input

    输入一行包含三个正整数N,k和P.
    3<=3k<=N<=3000,10^4<=p<=2×10^9

    Output

    输出文件的包含一行一个整数,表示本质不同的方案数对p的余数。保证p
    一定是一个质数。

    Sample Input

    3 1 1000000009

    Sample Output

    2

    HINT

     

    Source

     
     
    本质是求有多少个n个元素的置换,有k个循环且其中每个循环长度至少是3。
    这样就设f[i][j]为1-i构成的有j个循环的每个循环至少是3的方案数。
    转移的话考虑一下是否新开一个循环即可。
     
    #include<bits/stdc++.h>
    #define ll long long
    #define maxn 1005
    using namespace std;
    int f[maxn*3][maxn],n,k,P;
    int jc[maxn*3],ni[maxn*3];
    
    inline int add(int x,int y){
    	x+=y;
    	return x>=P?x-P:x;
    }
    
    inline void dp(const int ha){
    	f[0][0]=1;
    	for(int i=3;i<=n;i++){
    		int tp=min(i,k);
    		for(int j=1;j<=tp;j++) f[i][j]=add(f[i-3][j-1]*(ll)(i-1)%ha*(ll)(i-2)%ha,f[i-1][j]*(ll)(i-1)%ha);
    	}
    }
    
    int main(){
    	scanf("%d%d%d",&n,&k,&P);
    	dp(P);
    	printf("%d
    ",f[n][k]);
    	return 0;
    }
    

      

  • 相关阅读:
    android 圆角图片的实现
    navigationView 的使用和布局文件的绑定
    android listview 的监听事件
    android第三方框架 xlistview 的使用
    android Baseadapter 和 ViewHolder的使用
    android 调用电话功能
    android 颜色对照
    Android_menu_SubMenu
    Android_menu_optionMenu
    Android_Menu_contextMenu
  • 原文地址:https://www.cnblogs.com/JYYHH/p/8504866.html
Copyright © 2011-2022 走看看