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的更多相关文章

  1. 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.. ...

  2. 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最后会得到一个同余 ...

  3. BZOJ1951 [Sdoi2010]古代猪文 【费马小定理 + Lucas定理 + 中国剩余定理 + 逆元递推 + 扩展欧几里得】

    题目 "在那山的那边海的那边有一群小肥猪.他们活泼又聪明,他们调皮又灵敏.他们自由自在生活在那绿色的大草坪,他们善良勇敢相互都关心--" --选自猪王国民歌 很久很久以前,在山的那 ...

  4. [bzoj2142]礼物(扩展lucas定理+中国剩余定理)

    题意:n件礼物,送给m个人,每人的礼物数确定,求方案数. 解题关键:由于模数不是质数,所以由唯一分解定理, $\bmod  = p_1^{{k_1}}p_2^{{k_2}}......p_s^{{k_ ...

  5. HDU-5446-UnknownTreasure(组合数,中国剩余定理)

    链接: http://acm.hdu.edu.cn/showproblem.php?pid=5446 题意: On the way to the next secret treasure hiding ...

  6. 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 ...

  7. 逆元 exgcd 费马小定理 中国剩余定理的理解和证明

    一.除法取模逆元 如果我们要通过一个前面取过模的式子递推出其他要取模的式子,而递推式里又存在除法 那么一个很尴尬的事情出现了,假如a[i-1]=100%31=7 a[i]=(a[i-1]/2)%31 ...

  8. 【模拟7.22】visit(卢卡斯定理&&中国剩余定理)

    如此显然的组合数我把它当DP做,我真是.... 因为起点终点已经确定,我们发现如果我们确定了一个方向的步数其他方向也就确定了 组合数做法1: 设向右走了a步,然后向左走了b=a-n步,设向上为c,向下 ...

  9. hdu1573-X问题-(扩展欧几里得定理+中国剩余定理)

    X问题 Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submiss ...

随机推荐

  1. itools安装程序无法创建临时文件夹

    做个记录: itools链接ios设备后,安装程序包时提示:无法创建临时文件夹 主要原因可能有以下几点 1.手机储存空间不足. 2.驱动组建被删除了,重启管理软件会自动跟新驱动. 解决办法:1.清除空 ...

  2. java并发编程JUC第九篇:CountDownLatch线程同步

    在之前的文章中已经为大家介绍了java并发编程的工具:BlockingQueue接口.ArrayBlockingQueue.DelayQueue.LinkedBlockingQueue.Priorit ...

  3. 想玩转JAVA高并发,这些概念你必须懂

    高并发高并发 它是互联网分布式系统架构设计中必须考虑的因素之一,通常是指,保证系统能够同时并行化处理海量请求 同步和异步 同步:发送一个请求,等待返回,然后再发送下一个请求.提交请求 -> 等待 ...

  4. Linux命令大全之搜索命令

    文件搜索命令(只能搜索文件) locate 文件名 在后台数据库中按文件名搜索,搜索速度快      /var/lib/mlocate(locate文件数据库)    这个数据库默认一天更新一次,强制 ...

  5. (1)Canal入门

    1.前言 在我们系统开发过程中,根据业务场景很多数据库数据并不会直接给用户访问的,需要同步保存到ElasticSearch.Redis等存储应用当中(例如最常见的是搜索页面的ElasticSearch ...

  6. 玩转html2canvas以及常见问题解决

    前端小伙伴经常会遇到页面截图或者把网页中指定的区域(某个大div)的内容转换成png的图片.这个时候常常会用到html2canvas库来实现,js真的很强大. 我最近也遇到了一个需求,需要把输入的文本 ...

  7. base64的实现原理

    base64是处理二进制数据的一种编码方式,可用于把二进制数据编码成64个可打印的字符. 学习base64之前,先了解一下什么是字节与编码 什么是字节 互联网中的数据都是用字节来表示的,一个字节有8位 ...

  8. 18、lnmp_wordpress安装

    18.1.[root@web01 nginx]# mysql -uroot -p123456 mysql> show databases; #显示所有的数据库: +--------------- ...

  9. flex发生错误积累。每次遇到错误记录一点点

    error #2044: 未处理的 ioerrorevent: text=error #2036: 加载未完成 出现这个问题,因为我是要实现图片编辑裁剪,然后上传.没有上传成功,出现上面的这个错误, ...

  10. hdu 3397 Sequence operation 线段树 区间更新 区间合并

    题意: 5种操作,所有数字都为0或1 0 a b:将[a,b]置0 1 a b:将[a,b]置1 2 a b:[a,b]中的0和1互换 3 a b:查询[a,b]中的1的数量 4 a b:查询[a,b ...