【Lucas组合数定理+中国剩余定理】Mysterious For-HDU 4373
Mysterious For-HDU 4373
题目描述
MatRush is an ACMer from ZJUT, and he always love to create some special programs. Here we will talk about one of his recent inventions.
This special program was called "Mysterious For", it was written in C++ language, and contain several simple for-loop instructions as many other programs. As an ACMer, you will often write some for-loop instructions like which is listed below when you are taking an ACM contest.
for (int i = 0; i < n; i++) {
for (int j = i; j < n; j++) {
for (int k = j; k < n; k++) {
blahblahblah();
}
}
}
Now, MatRush has designed m for-loop instructions in the "Mysterious For" program, and each for-loop variable was stored in an array a[], whose length is m.
The variable i represents a for-loop instructions is the i-th instruction of the "Mysterious For" program.There only two type of for-loop instructions will occur in MatRush's "Mysterious For" program:
1-type: if a for-loop belongs to 1-type, it will be an instruction like this:
for (int a[i] = 0; a[i] < n; a[i]++) {
...
}
2-type: if a for-loop belongs to 2-type, it will be an instruction like this:
for (int a[i] = a[i - 1]; a[i] < n; a[i]++) {
...
}
In addition, after the deepest for-loop instruction there will be a function called HopeYouCanACIt(), here is what's inside:
void HopeYouCanACIt() {
puts("Bazinga!");
}
So, the "Mysterious For" program, obviously, will only print some line of the saying: "Bazinga!", as it designed for.
For example, we can assume that n equals to 3, and if the program has three 1-type for-loop instructions, then it will run 3 3=27 times of the function HopeYouCanACIt(), so you will get 27 "Bazinga!" in total. But if the program has one 1-type for-loop instruction followed by two 2-type for-loop instructions, then it will run 3+2+1+2+1+1=10 times of that function, so there will be 10 "Bazinga!" on the screen.
Now MatRush has the loop length n and m loop instructions with certain type, then he want to know how many "Bazinga!" will appear on the screen, can you help him? The answer is too big sometimes, so you just only to tell him the answer mod his QQ number:364875103.
All for-loop instructions are surely nested. Besides, MatRush guaranteed that the first one belongs to the 1-type. That is to say, you can make sure that this program is always valid and finite. There are at most 15 1-type for-loop instructions in each program.
Input
First, there is an integer T(T<=50), the number of test cases.
For every case, there are 2 lines.
The first line is two integer n(1<=n<=1000000) and m(1<=m<=100000) as described above.
The second line first comes an integer k(1<=k<=15), represents the number of 1-type loop instructions, then follows k distinctive numbers, each number is the i-th 1-type loop instruction's index(started from 0), you can assume the first one of this k numbers is 0 and all numbers are ascending.
All none 1-type loop instructions of these m one belongs to 2-type.
题目大意
给你循环的类型,和循环的个数,求能循环几次。
分析
扩展Lucas定理+中国剩余定理:大意就是你在mod的p是一个合数,那么就把他拆成p1*p2,两个质数的乘机。
我们可以发现第一类循环最多就只有15个,我的思路的突破口就是在这个15。
我们把这些循环分成一个一个的区块,每一个区块的第一个循环就是第一类循环,那么就是要求出每个循环块的答案在相乘就可以了。
那么我们看到每一个循环块,它的本质就是要取出x个数,但是每一个数都是可以相同的。(注:和每一个数都不一样的不一样,不一样的话答案就非常简单是 \(C^x_n\) )
第一重循环就是n次,第二次循环后面的循环都是第二层循环,那么第二重循环就是\(C^2_{n}+n\),以此类推,那么第三重循环就是$ C^3_{n+2} $,可以理解成在末尾在放两个数,但是所有的数都不能相同。
第三层的推导:

那么我们就得到了结论:第m层循环的次数为\(C^m_{n+m-1}\)
但是由于q不是一个质数,而是两个质数的乘机,所以先用卢卡斯分别求出余数的乘机,再列出等式发现是一个同余方程,就可以使用中国剩余定理或者费马小定理算求解答案。
AC代码
#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <queue>
#include <cctype>
#include <cmath>
#include <time.h>
#include <map>
#include <set>
#include <vector>
using namespace std;
#define ms(a,b) memset(a,b,sizeof(a))
typedef long long ll;
const int maxn=1000003;
const int maxm=100003;
const int mod=364875103;
const int mod1=97;
const int mod2=3761599;
int n,m;
ll p1[mod1+10],p2[mod2+10];
void init(){
p1[0]=1,p2[0]=1;
for (int i=1;i<=mod2;i++) p2[i]=p2[i-1]*i%mod2;
for (int i=1;i<=mod1;i++) p1[i]=p1[i-1]*i%mod1;
}
inline int read(){
int X=0,w=0; char ch=0;
while(!isdigit(ch)) {w|=ch=='-';ch=getchar();}
while(isdigit(ch)) X=(X<<3)+(X<<1)+(ch^48),ch=getchar();
return w?-X:X;
}
ll inv(ll x,ll y,ll mod) {
ll ret=1;
while (y) {
if (y&1) ret=ret*x%mod;
x=x*x %mod;
y>>=1;
}
return ret;
}
ll calc1(int n,int m) {
if (n<m) return 0;
ll x1=p1[n],x2=p1[m],x3=p1[n-m];
return x1*inv(x2,mod1-2,mod1)%mod1*inv(x3,mod1-2,mod1)%mod1;
}
ll calc2(int n,int m) {
if (n<m) return 0;
ll x1=p2[n],x2=p2[m],x3=p2[n-m];
return x1*inv(x2,mod2-2,mod2)%mod2*inv(x3,mod2-2,mod2)%mod2;
}
ll lucas2(int n,int m) {
if (n<m) return 0;
if (m==0) return 1;
return calc2(n%mod2,m%mod2)*lucas2(n/mod2,m/mod2)%mod2;
}
ll lucas1(int n,int m) {
if (n<m) return 0;
if (m==0) return 1;
return calc1(n%mod1,m%mod1)*lucas1(n/mod1,m/mod1)%mod1;
}
ll chinese(ll a[]) {
ll x1=inv(mod1,mod2-2,mod2)*a[1]%mod*mod1%mod;
ll x2=inv(mod2,mod1-2,mod1)*a[0]%mod*mod2%mod;
return (x1+x2)%mod;
}
ll solve(int n,int m) {
ll ans[2];
ans[0]=lucas1(n,m);
ans[1]=lucas2(n,m);
return chinese(ans);
}
int main()
{
int cas=read();
init();
for (int t=1;t<=cas;t++) {
n=read(),m=read();
int k=read(),x=read();
ll ans=1;
for (int i=1;i<k;i++) {
int y=read();
ans=ans*solve(n+y-x-1,y-x)%mod;
x=y;
}
ans=ans*solve(n+m-x-1,m-x)%mod;
printf("Case #%d: %lld\n",t,ans);
}
return 0;
}
【Lucas组合数定理+中国剩余定理】Mysterious For-HDU 4373的更多相关文章
- Hdu 5446 Unknown Treasure (2015 ACM/ICPC Asia Regional Changchun Online Lucas定理 + 中国剩余定理)
题目链接: Hdu 5446 Unknown Treasure 题目描述: 就是有n个苹果,要选出来m个,问有多少种选法?还有k个素数,p1,p2,p3,...pk,结果对lcm(p1,p2,p3.. ...
- hdu 5446(2015长春网络赛J题 Lucas定理+中国剩余定理)
题意:M=p1*p2*...pk:求C(n,m)%M,pi小于10^5,n,m,M都是小于10^18. pi为质数 M不一定是质数 所以只能用Lucas定理求k次 C(n,m)%Pi最后会得到一个同余 ...
- BZOJ1951 [Sdoi2010]古代猪文 【费马小定理 + Lucas定理 + 中国剩余定理 + 逆元递推 + 扩展欧几里得】
题目 "在那山的那边海的那边有一群小肥猪.他们活泼又聪明,他们调皮又灵敏.他们自由自在生活在那绿色的大草坪,他们善良勇敢相互都关心--" --选自猪王国民歌 很久很久以前,在山的那 ...
- [bzoj2142]礼物(扩展lucas定理+中国剩余定理)
题意:n件礼物,送给m个人,每人的礼物数确定,求方案数. 解题关键:由于模数不是质数,所以由唯一分解定理, $\bmod = p_1^{{k_1}}p_2^{{k_2}}......p_s^{{k_ ...
- HDU-5446-UnknownTreasure(组合数,中国剩余定理)
链接: http://acm.hdu.edu.cn/showproblem.php?pid=5446 题意: On the way to the next secret treasure hiding ...
- ACM-ICPC 2015 Changchun Preliminary Contest J. Unknown Treasure (卢卡斯定理+中国剩余定理)
题目链接:https://nanti.jisuanke.com/t/A1842 题目大意:给定整数n,m,k,其中1≤m≤n≤1018,k≤10, 然后给出k个素数,保证M=p[1]*p[2]……*p ...
- 逆元 exgcd 费马小定理 中国剩余定理的理解和证明
一.除法取模逆元 如果我们要通过一个前面取过模的式子递推出其他要取模的式子,而递推式里又存在除法 那么一个很尴尬的事情出现了,假如a[i-1]=100%31=7 a[i]=(a[i-1]/2)%31 ...
- 【模拟7.22】visit(卢卡斯定理&&中国剩余定理)
如此显然的组合数我把它当DP做,我真是.... 因为起点终点已经确定,我们发现如果我们确定了一个方向的步数其他方向也就确定了 组合数做法1: 设向右走了a步,然后向左走了b=a-n步,设向上为c,向下 ...
- hdu1573-X问题-(扩展欧几里得定理+中国剩余定理)
X问题 Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submiss ...
随机推荐
- Jmeter(五十二) - 从入门到精通高级篇 - jmeter之跨线程组传递参数(详解教程)
1.简介 之前分享的所有文章都是只有一个线程组,而且参数的传递也只在一个线程组中,那么如果需要在两个线程组中传递参数,我们怎么做呢?宏哥今天就给小伙伴或者童鞋们讲解一下,如何实现在线程组之间传递参数. ...
- 【Azure 机器人】微软Azure Bot 编辑器系列(4) : 使用语言生成功能[LG: Language Generation] (The Bot Framework Composer tutorials)
欢迎来到微软机器人编辑器使用教程,从这里开始,创建一个简单的机器人. 在该系列文章中,每一篇都将通过添加更多的功能来构建机器人.当完成教程中的全部内容后,你将成功的创建一个天气机器人(Weather ...
- NOIP模拟测试10「大佬·辣鸡·模板」
大佬 显然假期望 我奇思妙想出了一个式子$f[i]=f[i-1]+\sum\limits_{j=1}^{j<=m} C_{k \times j}^{k}\times w[j]$ 然后一想不对得容 ...
- NOIP模拟测试9「随·单·题」
liu_runda出的题,先$\%\%\%\%\%\%\%\%\%\%\%$为敬 随 考试时没有Qj 然后甚至没做,甚至没交 我不知道我怎么想的 这个题挺难改 你需要用到 循环矩阵快速幂,矩阵快速幂优 ...
- Linux安装界面简介
1.安装欢迎界面:install or upgrade an exsiting system:安装或升级现有系统 install system with basic video driver:安装过程 ...
- Ubuntu安装ibmmq
一.前言 安装整个ibmmq的过程中,真的气炸了,在网上搜索到的答案千篇一律,一个安装部署文档居然没有链接地址:为了找到这个开发版本的下载地址找了一下午,不容易啊.也提醒了自己写博文还是得有责任心,把 ...
- rust漫游 - 写时拷贝 Cow<'_, B>
rust漫游 - 写时拷贝 Cow<'_, B> Cow 是一个写时复制功能的智能指针,在数据需要修改或者所有权发生变化时使用,多用于读多写少的场景. pub enum Cow<'a ...
- ES6学习笔记之 let与const
在js中,定义变量时要使用var操作符,但是var有许多的缺点,如:一个变量可以重复声明.没有块级作用域.不能限制修改等. //缺点1:变量可以重复声明 var a=1; var a=2; conso ...
- 没有指定非静态方法,Unity与Android通信错误
报错信息: AndroidJavaException: java.lang.NoSuchMethodError: no non-static method with name='InstallApk' ...
- Docker安装运行Portainer
基本简介 Portainer是一个轻量级的docker环境管理UI,可以用来管理docker宿主机和docker swarm集群.他的轻量级,轻量到只要个不到100M的docker镜像容器就可以完整的 ...