第八场 hdu 6143 Killer Names(思维题)

http://acm.hdu.edu.cn/showproblem.php?pid=6143

题目大意:有名和姓两种字符串,每种字符串长度都是n个字符,名和姓加起来的字符种类数最多是m个,问满足条件的字符串有多少种?

解题思路:我们能够枚举左边的字符种数是x,那么右边就有(m-x)n种排列方式。我们知道左边的排列方式数量是C(m,x)*f(x)。其中f(x)=(xn-C(x,x-1)*f(x-1)-C(x,x-2)*f(x-2)……C(x,1)*f(1))。最后结果就是枚举每一个x,对C(m,x)*f(x)*(m-x)n求和就可以了。

AC代码:

 1 #include <iostream>
 2 #include <bits/stdc++.h>
 3 using namespace std;
 4 const long long mod=1e9+7;
 5 long long a[2005][2005],num[2005];
 6 long long  pow_(int n,int m)
 7 {
 8     long long tmp=m,ans=1;
 9     while(n)
10     {
11         if(n&1)
12         {
13             ans=(ans*tmp)%mod;
14         }
15         tmp=(tmp*tmp)%mod;
16         n=n/2;
17     }
18     return ans%mod;
19 }
20 int main()
21 {
22     int t,n,m;
23     for(int i=1;i<=2002;i++)
24     {
25         a[i][0]=1,a[i][i]=1;
26         for(int j=1;j<i;j++)
27         {
28             a[i][j]=(a[i-1][j-1]+a[i-1][j]+mod)%mod;
29         }
30     }
31     while(~scanf("%d",&t))
32     {
33         while(t--)
34         {
35             memset(num,0,sizeof(num));
36             scanf("%d%d",&n,&m);
37             long long ans,tmp=1;
38             if(m>n)
39             {
40                 ans=0,tmp=0;
41                 for(int i=1;i<=n;i++)
42                 {
43                     tmp=0;
44                     for(int j=1;j<i;j++)
45                     tmp=(tmp+a[i][j]*num[j])%mod;
46                     num[i]=(pow_(n,i)-tmp+mod)%mod;
47                     ans=(ans+(((a[m][i]*num[i])%mod)*pow_(n,m-i))%mod+mod)%mod;
48                 }
49             }
50             else
51             {
52                 ans=0,tmp=0;
53                 for(int i=1;i<=m-1;i++)
54                 {
55                     tmp=0;
56                     for(int j=1;j<i;j++)
57                     tmp=(tmp+a[i][j]*num[j])%mod;
58                     num[i]=(pow_(n,i)-tmp+mod)%mod;
59                     ans=(ans+(((a[m][i]*num[i])%mod)*pow_(n,m-i))%mod+mod)%mod;
60                 }
61             }
62             printf("%lld\n",ans%mod);
63         }
64     }
65     return 0;
66 }
时间: 2024-10-15 14:36:16

第八场 hdu 6143 Killer Names(思维题)的相关文章

2017多校第8场 HDU 6143 Killer Names 容斥,组合计数

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6143 题意:m种颜色需要为两段长度为n的格子染色,且这两段之间不能出现相同的颜色,问总共有多少种情况. 解法:枚举要为这两段分配的颜色数目分别为 i,j ,则在第一段总共有 C(m,i) 种选取方案,在第二段总共有 C(m?i,j) 种选取方案.而在每段内部,我们设 F(n,x) 为长度为 n 的格子使用 x 种颜色(等于 x )染色的方案数.则根据容斥原理 F(n,x)=x^n?C(x,1)*(x

HDU - 6143 Killer Names(dp记忆化搜索+组合数)

题意:从m种字母中选取字母组成姓名,要求姓和名中不能有相同的字母,姓和名的长度都为n,问能组成几种不同的姓名. 分析: 1.从m种字母中选取i种组成姓,剩下m-i种组成名. 2.i种字母组成长度为n的姓-----可转换成用i种颜色给n个球染色,记忆化搜索 dfs(n,i)---用i种颜色给n个球染色的方案数 先给第1个小球涂色,有m种选择,假设涂色为color[1], 那么剩下n-1个小球: 如果继续使用color[1],则问题转化为用m种颜色给n-1个小球涂色: 如果不再使用color[1],

HDU 5752 Sqrt Bo (思维题) 2016杭电多校联合第三场

题目:传送门. 题意:一个很大的数n,最多开5次根号,问开几次根号可以得到1,如果5次还不能得到1就输出TAT. 题解:打表题,x1=1,x2=(x1+1)*(x1+1)-1,以此类推.x5是不超过long long的,判断输出即可. #include <iostream> #include <cstdio> #include <cstring> #include <cmath> using namespace std; typedef long long

hdu - 1172 猜数字 (思维题)

http://acm.hdu.edu.cn/showproblem.php?pid=1172 这个题换一种想法,可以找出四位数中所有满足条件的数看是否只有一个. 1 #include <iostream> 2 #include <cstdio> 3 #include <cmath> 4 #include <vector> 5 #include <cstring> 6 #include <string> 7 #include <a

hdu 5671 Matrix(BC——思维题)

题目链接:acm.hdu.edu.cn/showproblem.php?pid=5671 Matrix Time Limit: 3000/1500 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others) Total Submission(s): 891    Accepted Submission(s): 371 Problem Description There is a matrix M that has n rows

2014 HDU多校弟八场H题 【找规律把】

看了解题报告,发现看不懂 QAQ 比较简单的解释是这样的: 可以先暴力下达标,然后会发现当前数 和 上一个数 的差值是一个 固定值, 而且等于当前数与i(第i个数)的商, 于是没有规律的部分暴力解决,有规律的套公式 //#pragma comment(linker, "/STACK:16777216") //for c++ Compiler #include <stdio.h> #include <iostream> #include <cstring&g

多校第八场:图论出度

HDU 4948 这题比赛的时候遗憾了,我看了这道题,然后觉得挺简单的. 刚开始一看题上,想到的就是拓扑排序,然后脑子想啊想--感觉就是拓扑排序的逆序,然后发现挺水的-- 因为说了要想发展某个城市的话,就必须有另一个城市作为它发展的前提,即城市u->w这样连边,表示要想发展城市w,前提是u已经是发展过的城市了.那这样的话不是很简单嘛. 即统计出出度最多的就是第一个要发展的城市了,因为u->w这样连边可以看出算出出度最多的依次从大到小排序就行了. 哎呀,不过可惜了,因为看见没人交这题,然后也不敢

多校第六场 HDU 4927 JAVA大数类

题目大意:给定一个长度为n的序列a,每次生成一个新的序列,长度为n-1,新序列b中bi=ai+1?ai,直到序列长度为1.输出最后的数. 思路:这题实在是太晕了,比赛的时候搞了四个小时,从T到WA,唉--对算组合还是不太了解啊,现在对组合算比较什么了-- import java.io.*; import java.math.*; import java.util.*; public class Main { public static void main(String[] args) { Sca

hdu 4972 A simple dynamic programming problem (转化 乱搞 思维题) 2014多校10

题目链接 题意:给定一个数组记录两队之间分差,只记分差,不记谁高谁低,问最终有多少种比分的可能性 分析: 类似cf的题目,比赛的时候都没想出来,简直笨到极点..... 1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cstdlib> 5 #include <cmath> 6 #include <vector> 7 #include &