【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 ...
随机推荐
- Optim High Performance Unload [HPU]
目录 一.简介 二.安装 三.基本配置 四.卸数 4.1. 命令行导出 4.2. 控制文件 4.2.1. 从表空间容器卸数 4.2.2. 从备份镜像中卸数 4.2.3. 控制文件语法参考 4.3. 存 ...
- leetcode5697. 检查二进制字符串字段
5697. 检查二进制字符串字段给你一个二进制字符串 s ,该字符串 不含前导零 . 如果 s 最多包含 一个由连续的 '1' 组成的字段 ,返回 true .否则,返回 false . 示例 ...
- Python常用数据结构(列表)
Python中常用的数据结构有序列(如列表,元组,字符串),映射(如字典)以及集合(set),是主要的三类容器 内容 序列的基本概念 列表的概念和用法 元组的概念和用法 字典的概念和用法 各类型之间的 ...
- 简易版JDBC连接池
JDBC连接池mini版的实现 首先是工具类 DbUtil 主要参数就是Driver.User.PWD等啦,主要用于建立连接 URL需要注意的是SSL和serverTimezone参数,和mysql驱 ...
- PUN丨实用API
原文地址:PUN丨实用API 当前房间人数 int num = PhotonNetwork.CurrentRoom.PlayerCount; 当前脚本是否属于当前玩家 //需继承MonoBehavio ...
- 堆和栈的内存分布&一些关于内存泄露、栈溢出和野指针的内容(头秃
内存泄漏&栈溢出 C++中,我们主要涉及的内存是栈和堆, 堆 (By programmer) 申请后由程序员主动释放,遗忘后果严重: 栈 (By compiler)需要时由编译器分配,在不需 ...
- 详细解释 使用FileReference类加载和保存本地文件
一般而言,用户不希望web浏览器中运行的应用程序访问电脑硬盘里的文件.然而,随着基于浏览器(browser-based)的富因特网应用程序的增多,一些应用程序迫切需要访问用户所选择的文件,或者将文件保 ...
- 关于vue告警 More than 1 blank line not allowed
开发vue-cli脚手架工程,eslint规范检查工具告警笔记 More than 1 blank line not allowed 代码空格不允许超过1行,把多余的空行删除就可以了
- Redis 过期时间解析
文章参考:<Redis 设计与实现>黄建宏 设置过期时间 通过 EXPIRE 或者 PEXPIRE 命令,客户端可以以秒或毫秒精度为数据库中的某个键设置生存时间 TTL (Time To ...
- 【译】GO语言:管理多个错误
原文:https://medium.com/a-journey-with-go/go-multiple-errors-management-a67477628cf1 关于开发者使用Go遇到的最大挑 ...