【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 ...
随机推荐
- 0算法基础学算法 搜索篇第二讲 BFS广度优先搜索的思想
dfs前置知识: 递归链接:0基础算法基础学算法 第六弹 递归 - 球君 - 博客园 (cnblogs.com) dfs深度优先搜索:0基础学算法 搜索篇第一讲 深度优先搜索 - 球君 - 博客园 ( ...
- 2021年Wordpress博客搭建
2021年WordPress博客搭建教程 这是一篇关于2021最新版的WP个人博客搭建教程.整篇文章会事无巨细的一步步讲述搭建博客的每一步. 0.前言 随着互联网和移动互联网的飞速发展,博客这一功能恍 ...
- 【NX二次开发】导出x_t、导入x_t例子,UF_PS_export_data、UF_PS_import_data
获取blockUI 体收集器选择的体,导出x_t: std::vector<TaggedObject*>objects = bodySelect0->GetSelectedObjec ...
- day20200911
UG12.0进入运动仿真模块 新建仿真 定义固定连杆 定义其他连杆 定义运动副 定义驱动 定义解算方案并求解 导出动画
- 在VScode 中使用RT-Thread Studio初体验
前言 工欲善其事,必先利其器,VScode是什么东东,想必大家都非常熟悉了,丰富的插件,有好的开发界面,是很多程序开发者的不二之选,RT-Thread竟然也开发了Vscode插件,真的是非常的nice ...
- NOIP模拟测试21「折纸·不等式」
折纸 题解 考试时无限接近正解,然而最终也只是接近而已了 考虑模拟会爆炸,拿手折纸条试一试,很简单 考你动手能力 代码 #include<bits/stdc++.h> using name ...
- Tkinter 吐槽之二:Event 事件在子元素中共享
背景 最近想简单粗暴的用 Python 写一个 GUI 的小程序.因为 Tkinter 是 Python 自带的 GUI 解决方案,为了部署方便,就直接选择了 Tkinter. 本来觉得 GUI 发展 ...
- git schnnel failed to receive handshake, SSLTLS connection failed
git schnnel failed to receive handshake, SSLTLS connection failed 报错,查看原因为git安装时ssl选择的不是openssl.重新安装 ...
- pip安装setuptools_rust报错
公司项目中有主备CDN存在,由于阿里云以及腾讯云的预热功能不支持自动(一般是云函数),所以就根据云厂商给的脚本稍作更改,手动传入数据来进行预热. 由于之前部署在centos7.7系统python2.7 ...
- 海康威视摄像头入侵+fofa(CVE-2017-7921)
海康威视摄像头入侵+fofa(CVE-2017-7921) By:Jesse 重保期间实在是太无聊,于是就找了个海康威视的摄像头日日玩,结果一玩就是一天呢哈哈哈. 1.漏洞编号 CVE-2017-79 ...