题目链接

Problem Description

Galen Marek, codenamed Starkiller, was a male Human apprentice of the Sith Lord Darth Vader. A powerful Force-user who lived during the era of the Galactic Empire, Marek originated from the Wookiee home planet of Kashyyyk as the sole offspring of two Jedi Knights—Mallie and Kento Marek—who deserted the Jedi Order during the Clone Wars. Following the death of his mother, the young Marek's father was killed in battle by Darth Vader. Though only a child, Marek possessed an exceptionally strong connection to the Force that the Dark Lord of the Sith sought to exploit.

When Marek died in 2 BBY, shortly after the formation of the Alliance, Vader endeavored to recreate his disciple by utilizing the cloning technologies of the planet Kamino. The accelerated cloning process—an enhanced version of the Kaminoan method which allowed for a rapid growth rate within its subjects—was initially imperfect and many clones were too unstable to take Marek's place as the Dark Lord's new apprentice. After months of failure, one particular clone impressed Vader enough for him to hope that this version might become the first success. But as with the others, he inherited Marek's power and skills at the cost of receiving his emotions as well, a side effect of memory flashes used in the training process.

— Wookieepedia

Darth Vader is finally able to stably clone the most powerful soilder in the galaxy: the Starkiller. It is the time of the final strike to destroy the Jedi remnants hidden in every corner of the galaxy.

However, as the clone army is growing, giving them names becomes a trouble. A clone of Starkiller will be given a two-word name, a first name and a last name. Both the first name and the last name have exactly n characters, while each character is chosen from an alphabet of size m. It appears that there are m2n possible names to be used.

Though the clone process succeeded, the moods of Starkiller clones seem not quite stable. Once an unsatisfactory name is given, a clone will become unstable and will try to fight against his own master. A name is safe if and only if no character appears in both the first name and the last name.

Since no two clones can share a name, Darth Vader would like to know the maximum number of clones he is able to create.

Input
The First line of the input contains an integer T (T≤10), denoting the number of test cases.

Each test case contains two integers n and m (1≤n,m≤2000).

Output
For each test case, output one line containing the maximum number of clones Vader can create.

Output the answer mod 109+7

Sample Input
2
3 2
2 3

Sample Output
2
18

题意:
有m种字符(可以不用完),组成两个长度为n的字符串,要求这两个字符串中不含有相同的字符。

求有多少种方式组成这两个字符串。

分析:思路一,容斥+排列组合

利用容斥的思想来计算一下下面的式子:

定义:f[n][i]表示长度为n的字符串用i种字符填充的方法数。

f[n][1]=1
f[n][2] = 2^n - C(2,1)f[n][1]; 两种的所有填充方式-一种的填充方式。
f[n][3] = 3^n - C(3,1)
f[n][1] - C(3,2)f[n][2];...
...
f[n][m] = m^n - sigma[1<=i<m]C(m,i)
f[n][i];

那么可以枚举左边这个n长度字符串的组合方式用去i种字符,那么剩下那个字符串用剩下的字符任意组合即可。

注意m大于n的情况。以及在我们求C(m,i)的时候,这个式子可以转换为m!/(i!*(m-i)!),这里涉及到除法的操作,这样的话可能在除的过程中会造成精度的丢失,所以我们将除数转换为它们本身的逆元。又因为取余的数只一个质数,可以直接用费马小定理求逆元。

代码:

#include<bits/stdc++.h>
#define LL long long
using namespace std;
const int N = 2005;
const int mod = 1e9 + 7;
LL fac[N], inv[N],f[N][N],ans;
LL Pow(LL a,LL b)///整数快速幂
{LL ans = 1;while(b){if(b&1) ans = ans*a%mod;a = a*a%mod;b >>= 1;}return ans;
}void init()
{fac[0] = 1;for(int i = 1; i < N; i++)fac[i] = fac[i-1]*i%mod;///i!inv[0] = inv[1] = 1;for(int i = 2; i < N; i++){inv[i] = Pow(fac[i],mod-2);///i!的逆元,因为后期求C(n,m)的时候要用到相除,可能会丢失精度,所以将除数转换为本身的逆元}
}LL C(int n,int m)///n!/(m!*(n-m)!)
{return fac[n]*inv[m]%mod*inv[n-m]%mod;
}void solve(int n,int m)
{for(int i = 1; i <= min(n,m); i++){f[n][i] = Pow(i,n);///最开始的时候是i^nfor(int j = 1; j < i; j++)///逐渐减去C(i,j)*f[n][j]{f[n][i] = (f[n][i]-f[n][j]*C(i,j)%mod+mod)%mod;}}
}int main()
{int T;int n, m;init();scanf("%d",&T);while(T--){scanf("%d%d",&n,&m);solve(n,m);ans = 0;int mis;if(m>n) mis = n;else mis = m-1;for(int i = 1; i <= mis; i++){ans = (ans+C(m,i)*f[n][i]%mod*Pow(m-i,n)%mod)%mod;}printf("%lld\n",ans);}return 0;
}

思路二:dp递推

设定义:dp[i][j],前i个位置使用j种字符的方案数,dp在求解的过程中就已经不存在相互矛盾的情况了。
当前位置,只考虑使用使用过的j种 或者 考虑没有使用过的 m-j种
n*n的转移
前半部分用了j种, 剩下 的 m-j 全用在 后半部分,快速密 乘起来 累加就是ans

代码:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod = 1e9 + 7;
const int maxn = 2010;
ll dp[maxn][maxn];ll quick_pow(ll a, ll b)///整数快速幂
{ll ans = 1;while (b){if (b & 1)    ans = ans*a%mod;a = a*a%mod;b >>= 1;}return ans;
}int main()
{int T;scanf("%d",&T);while(T--){int n,m;scanf("%d%d",&n,&m);dp[1][1]=m;///第一个位置放置一种字符的方案数有且仅有一个for(int i=2; i<=n; i++)///从第二个位置遍历到第n个位置{for(int j=1; j<=i&&j<=m; j++)///前i个位置可以选择放的不同字符的个数最少为1个,最多为i个(每个位置上的字符都不一样){/*要使前i个位置上有j个不同的字符,考虑两种方案数1.前i-1个位置上就已经有了j个不同的字符了,那么第j个位置上就可以从这j个字符中任意选择一个2.前i-1个位置上只有j-1个不同的字符,那么第j个位置上的字符就不能选择已经选过的j-1个字符了,需要从剩余的(m-(j-1))个字符里面任意的选择一个这两种方案数共同构成*/dp[i][j]=(dp[i-1][j]*j%mod+dp[i-1][j-1]*(m-j+1)%mod)%mod;}}/*dp求出来的只是组成姓这n个字符的不同的方案数,我们还要考虑组成名的不同的方案数组成名的字符要从剩余的(m-j)个字符里面选择,每个字符都对应着n中摆放位置,两两组合的方案数肯定是乘的关系最后将求得的结果累加*/ll ans=0;for(int j=1; j<m; j++){ans=(ans+dp[n][j]*quick_pow(m-j,n)%mod)%mod;}printf("%lld\n",ans);}return 0;
}

转载于:https://www.cnblogs.com/cmmdc/p/7384531.html

2017ACM暑期多校联合训练 - Team 8 1011 HDU 6143 Killer Names (容斥+排列组合,dp+整数快速幂)...相关推荐

  1. 2017ACM暑期多校联合训练 - Team 7 1009 HDU 6128 Inverse of sum (数学计算)

    题目链接 Problem Description There are n nonnegative integers a1-n which are less than p. HazelFan wants ...

  2. 2017 ACM暑期多校联合训练 - Team 3 1008 HDU 6063 RXD and math (莫比乌斯函数)...

    题目链接 Problem Description RXD is a good mathematician. One day he wants to calculate: ∑i=1nkμ2(i)×⌊nk ...

  3. 2018ACM暑期多校联合训练参(bao)赛(zha)记

    (这毁了我一个暑假的东西) 时间 2018-7-23至2018-8-22,一星期2场,共10场,每场5个小时. 题目链接(楼教主:"是男人就过八(116)题") 评分规则 单场得分 ...

  4. HDU 2019 Multi-University Training Contest 1 杭电2019多校联合训练赛 第一场 1001 Blank (6578)

    HDU 2019 Multi-University Training Contest 1 杭电2019暑期多校集训第一场 1001 Blank (6578) Problem Description T ...

  5. 2022牛客暑期多校训练营训练日志

    2022牛客暑期多校训练营1 G - Lexicographical Maximum 签到题. A - Villages: Landlines 简化题意:给你 nnn 条线段,问你把这些线段铺到数轴上 ...

  6. 2022杭电多校九 1008-Shortest Path in GCD Graph(质因子+容斥)

    题目链接:杭电多校九 - Virtual Judge 题目: 样例输入: 6 2 4 5 3 6 样例输出: 1 1 2 2 题意:给定n个点的完全图,两个点之间的距离为他们的gcd,q次询问,每次询 ...

  7. 2018 多校联合训练 10

    Problem A Problem B Problem C Problem D Problem E 每个数的因子个数大概100个(最多128个) 那么把这些数全都放到集合里面就可以了. 然后直接上启发 ...

  8. 牛客网多校联合训练1 J Different Integers(可持久化线段树/莫队)

    题意:给你一个L,R区间,让你求1-L和R-n中有多少个数 思路:最美不过夕阳红,一直没想到拼接起来,之前想到拼接,但想的是每次都进行拼接,所以是一个n2lg的操作,最后想到了拼接全部,然后就是一个经 ...

  9. 2016多校联合训练1 B题Chess (博弈论 SG函数)

    题目大意:一个n(n<=1000)行,20列的棋盘上有一些棋子,两个人下棋,每回合可以把任意一个棋子向右移动到这一行的离这个棋子最近的空格上(注意这里不一定是移动最后一个棋子),不能移动到棋盘外 ...

最新文章

  1. idea的tomcat配置文件在哪里修改_MyBatis配置文件详解
  2. mysql5.5数据库名_mysql5.5数据库名
  3. NVL 和NVL2函数
  4. openfalcon 组件监控_运维监控系统之Open-Falcon
  5. 【数据竞赛】“达观杯”文本智能处理挑战赛3
  6. HashMap的底层原理 cr:csdn:zhangshixi
  7. 数字PCR(DPCR)和QPCR行业调研报告 - 市场现状分析与发展前景预测
  8. 时隔六年,FreeDOS终于更新,是否还能与Windows一战?
  9. python 列表生成式 字典生成式
  10. 超全面的权限系统设计方案!
  11. 如何打开KML和KMZ文件并与卫星影像叠加
  12. windows传文件给linux工具
  13. Roaring位图具有更好的位图性能
  14. Java Email——使用Java程序收发电子邮件
  15. 【JAVA今法修真】 第七章 洞天风云起,索引混乱平
  16. codeblock的c语言编译,CodeBlocks无法编译的原因和解决办法
  17. 我赌你的电脑里肯定有漏洞—不信测测看
  18. BI神器Power Query(19)-- PQ提取商品信息
  19. 测试前置条件及测试点
  20. 联想开机启动项按哪个_联想笔记本按哪个键进入u盘启动

热门文章

  1. 【总结】PHP常见面试题汇总(一)。。。
  2. A*算法解决8数码问题python实现
  3. Eclipse正版(官网下载)安装教程及如何在win7或者win10安装配置jdk1.8
  4. 5000的游戏电脑计算机配置,5000元电脑配置单,5000游戏电脑配置,直播电脑配置
  5. JAVA Applet——绘制心形曲线
  6. Jetson Xavier NX系统安装至 nvme 硬盘
  7. Java_银行开户存取款
  8. 只要60页!金融量化博士总结的Python数据分析入门知识手册
  9. MTK_android11_以太网(内网)和WIFI(外网)共存
  10. 纸壳CMS体验升级,快速创建页面,直接在页面中修改内容