数论 Day 13
数论_CRT(中国剩余定理)& Lucas (卢卡斯定理)
前言
又是一脸懵逼的一天。
正文
按照道理来说,我们应该先做一个介绍。
中国剩余定理
中国剩余定理,Chinese Remainder Theorem,又称孙子定理,给出了一元线性同余方程组的有解判定条件,并用构造法给出了通解的具体形式。

扩展中国剩余定理
在一般情况下,要求任两个数互质这个条件太苛刻了,CRT派不上用场,我们需要一个更具普遍性的结论,这就是EX-CRT。虽然是称为EX-CRT,但这个定理并没有直接用到CRT的结论。
typedef long long ll;
;
// m为模数组,a为余数数组,0~n-1
ll m[maxn], a[maxn];
ll exgcd(ll a, ll b, ll &x, ll &y) {
) {
x = ; y = ;
return a;
}
ll ans = exgcd(b, a % b, y, x);
y -= a / b * x;
return ans;
}
ll excrt() {
ll lcm = m[], last_a = a[];
; i < n; i++) {
ll lcm_a = ((a[i] - last_a) % m[i] + m[i]) % m[i];
ll k = lcm, x, y;
ll gcd = exgcd(lcm, m[i], x, y);
ll mod = m[i] / gcd;
x = (x * lcm_a / gcd % mod + mod) % mod;
lcm = lcm / gcd * m[i], last_a = (last_a + k * x) % lcm;
}
return (last_a % lcm + lcm) % lcm;
}
卢卡斯定理
卢卡斯定理是关于组合数和同余的定理,它表明当p为素数时:

因为当m>n时,二项式系数为0,那么二项式系数即组合数能被p整除等价于在p进制下,存在某一位m的数值大于对应的n的数值。
基于母函数可以简单证明这个定理。

可以用除法和取模方便的在循环中求出各个系数,代码如下:
typedef long long ll;
;
;
void init() {
F[] = ;
; i < maxn; i++)
F[i] = i * F[i - ] % mod;
}
ll qpow(ll a, ll b) {
ll ans = ;
while(b) {
) ans = ans * a % mod;
b >>= ; a = a * a % mod;
}
return ans;
}
ll lucas(ll N, ll M) {
ll ans = ;
while(N & M) {
ll n = N % mod, m = M % mod;
;
ans = ans * F[a] % mod * qpow(F[m] * F[n - m] % mod, mod - ) % mod;
N /= p; M /= p;
}
return ans;
}
扩展卢卡斯定理
卢卡斯定理同样不能处理模数不是素数的情况,这时便需要扩展卢卡斯定理。我们一步步分析如何求解模数不是素数的组合数问题。
完整代码如下:
typedef long long ll;
;
ll n, m, p;
ll qpow(ll a, ll b, ll mod) {
ll ans = ;
while(b) {
) ans = ans * a % mod;
b >>= ; a = a * a % mod;
}
return ans;
}
ll fac(ll n, ll p, ll pk) {
;
ll ans = ;
; i < pk; i++)
if (i % p) ans = ans * i % pk;
ans = qpow(ans, n / pk, pk);
int npk = n % pk;
; i <= npk; i++)
if (i % p) ans = ans * i % pk;
return ans * fac(n / p, p, pk) % pk;
}
ll exgcd(ll a, ll b, ll &x, ll &y) {
) {
x = ; y = ;
return a;
}
ll ans = exgcd(b, a % b, y, x);
y -= a / b * x;
return ans;
}
ll inv(ll a, ll p) {
, p);
}
ll C(ll n, ll m, ll p, ll pk) {
;
ll fn = fac(n, p, pk),
fm = fac(m, p, pk),
fn_m = fac(n - m, p, pk),
cnt = ;
for (ll i = n; i; i /= p)
cnt += i / p;
for (ll i = m; i; i /= p)
cnt -= i / p;
for (ll i = n - m; i; i /= p)
cnt -= i / p;
return fn * inv(fm * fn_m % pk, pk) % pk * qpow(p, cnt, pk) % pk;
}
ll a[N], mod[N]; // a[]是通过卢卡斯分解出来的组合数值,m[]是对应的模数
int cnt; // 质因数的种数
ll CRT() {
ll M = , ans = ;
; i < cnt; i++)
M *= mod[i];
; i < cnt; i++)
ans = (ans + a[i] * (M / mod[i]) % M * inv(M / mod[i], mod[i]) % M) % M;
return ans;
}
ll exlucas(ll n, ll m, ll p) {
ll sqrtp = sqrt(p + 0.5);
; p > && i <= sqrtp; i++) {
ll pk = ;
)
p /= i, pk *= i;
)
a[cnt] = C(n, m, i, pk), mod[cnt++] = pk;
}
)
a[cnt] = C(n, m, p, p), mod[cnt++] = p;
return CRT();
}
题目
其实这篇博客到这里几乎就可以没了,因为我。。。爆0了
难啊。。。
A题
Some people believe that there are three cycles in a person's life that start the day he or she is born. These three cycles are the physical, emotional, and intellectual cycles, and they have periods of lengths 23, 28, and 33 days, respectively. There is one peak in each period of a cycle. At the peak of a cycle, a person performs at his or her best in the corresponding field (physical, emotional or mental). For example, if it is the mental curve, thought processes will be sharper and concentration will be easier. Since the three cycles have different periods, the peaks of the three cycles generally occur at different times. We would like to determine when a triple peak occurs (the peaks of all three cycles occur in the same day) for any person. For each cycle, you will be given the number of days from the beginning of the current year at which one of its peaks (not necessarily the first) occurs. You will also be given a date expressed as the number of days from the beginning of the current year. You task is to determine the number of days from the given date to the next triple peak. The given date is not counted. For example, if the given date is 10 and the next triple peak occurs on day 12, the answer is 2, not 3. If a triple peak occurs on the given date, you should give the number of days to the next occurrence of a triple peak. This problem contains multiple test cases! The first line of a multiple input is an integer N, then a blank line followed by N input blocks. Each input block is in the format indicated in the problem description. There is a blank line between input blocks. The output format consists of N output blocks. There is a blank line between output blocks. Input You will be given a number of cases. The input for each case consists of one line of four integers p, e, i, and d. The values p, e, and i are the number of days from the beginning of the current year at which the physical, emotional, and intellectual cycles peak, respectively. The value d is the given date and may be smaller than any of p, e, or i. All values are non-negative and at most 365, and you may assume that a triple peak will occur within 21252 days of the given date. The end of input is indicated by a line in which p = e = i = d = -1. Output For each test case, print the case number followed by a message indicating the number of days to the next triple peak, in the form: Case 1: the next triple peak occurs in 1234 days. Use the plural form ``days'' even if the answer is 1. Sample Input 1 0 0 0 0 0 0 0 100 5 20 34 325 4 5 6 7 283 102 23 320 203 301 203 40 -1 -1 -1 -1 Sample Output Case 1: the next triple peak occurs in 21252 days. Case 2: the next triple peak occurs in 21152 days. Case 3: the next triple peak occurs in 19575 days. Case 4: the next triple peak occurs in 16994 days. Case 5: the next triple peak occurs in 8910 days. Case 6: the next triple peak occurs in 10789 days.
Biorhythms HDU-1370
题意
一个人有三个值(不知道是啥),然后每个值每到一个周期就会到达顶峰,求从d天开始,他三个值都到达顶峰是第几天。
思路
然而,三个周期都是质数,显然用的是中国剩余定理(CRT)
抽象一点来说,就是给你三个同余方程。
代码
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
using namespace std;
typedef long long ll;
ll exgcd(ll a, ll b, ll &x, ll &y)
{
if(!b)
{
x = ;
y = * ;
return a;
}
ll d = exgcd(b, a % b, x, y);
ll t = x;
x = y;
y = t - a / b * y;
return d;
}
ll inv(ll a,ll n)
{
ll y, d, x, fre, pf, qw;
/*cnt't*/
fre = pf = qw = ;
fre++, pf++, qw++;
/*can't*/
d = exgcd(a,n,x,y);
? (x + n) % n:-;
}
ll CN(ll leo, ll *a, ll *m)
{
ll M = , ret = ;
; i < leo; i ++)
M *= m[i];
; i < leo; i ++)
{
ll w = M / m[i];
ret = (ret + w * inv(w, m[i]) * a[i]) % M;
}
return (ret + M) % M;
}
int main()
{
ll t = , d;
ll a[],m[];
m[] = ;
m[] = ;
m[] = ;
/*GN*/
ll tea;
scanf("%lld", &tea);
while(true)
{
scanf(], &a[], &a[], &d);
] == - && a[] == - && a[] == - && d == -)
break;
ll ans = CN(, a, m);
if(ans <= d)
ans += ;
ans -= d;
printf("Case %lld: the next triple peak occurs in %lld days.\n", t, ans);
t++;
}
;
}
B题
F(x) is a polynomial in x with integer coefficients, here F(x) = (1+x)^a1 + (1+x)^a2 + ... + (1+x)^am. Given a1, a2, ... , am, find number of odd coefficients of F(x). Input The first line contains a single positive integer T( T <= 10000 ), indicates the number of test cases. For each test case: First line contains an integer N(1 <= N <= 15). Second line contains N integers a1, a2, ..., am ( 0 <= ai <= 2^45 ) Output For each test case: output the case number as shown and an the odd coefficients of F(x). Sample Input 4 1 1 1 3 2 1 3 3 1 2 3 Sample Output Case #1: 2 Case #2: 4 Case #3: 2 Case #4: 2 Hint Case #3: (1+x) + (1+x)^3 = 2 + 4x + 3x^2 + x^3. it contains 2 odd coefficients. Case #4: (1+x) + (1+x)^2 + (1+x)^3 = 3 + 6x + 4x^2 + x^3. it contains 2 odd coefficients.
Big Coefficients HDU-3929
题意
略
思路
显然是用卢卡斯,但我不知道为哈
未完待续
数论 Day 13的更多相关文章
- 洛谷P1621 集合 [2017年6月计划 数论13]
P1621 集合 题目描述 现在给你一些连续的整数,它们是从A到B的整数.一开始每个整数都属于各自的集合,然后你需要进行一下的操作: 每次选择两个属于不同集合的整数,如果这两个整数拥有大于等于P的公共 ...
- Educational Codeforces Round 13 D:Iterated Linear Function(数论)
http://codeforces.com/contest/678/problem/D D. Iterated Linear Function Consider a linear function f ...
- CodeForces 300C --数论
A - A Time Limit:2000MS Memory Limit:262144KB 64bit IO Format:%I64d & %I64u Submit Statu ...
- [Swust OJ 1125]--又见GCD(数论,素数表存贮因子)
题目链接:http://acm.swust.edu.cn/problem/1125/ Time limit(ms): 1000 Memory limit(kb): 65535 Descriptio ...
- ARZhu的数论初步
数论 2017年3月4日02:11:35 gcd 1. 原理: gcd( a, b ) = gcd( b, a - b ) -> gcd( a, b ) = gcd( b, b % a ) 2. ...
- HDU 1013.Digital Roots【模拟或数论】【8月16】
Digital Roots Problem Description The digital root of a positive integer is found by summing the dig ...
- 2017年浙江理工大学程序设计竞赛校赛 题解&源码(A.水, D. 简单贪心 ,E.数论,I 暴力)
Problem A: 回文 Time Limit: 1 Sec Memory Limit: 128 MB Submit: 1719 Solved: 528 Description 小王想知道一个字 ...
- [自用]数论和组合计数类数学相关(定理&证明&板子)
0 写在前面 本文受 NaVi_Awson 的启发,甚至一些地方直接引用,在此说明. 1 数论 1.0 gcd 1.0.0 gcd $gcd(a,b) = gcd(b,a\;mod\;b)$ 证明:设 ...
- 数论ex
数论ex 数学学得太差了补补知识点or复习 Miller-Rabin 和 Pollard Rho Miller-Rabin 前置知识: 费马小定理 \[ a^{p-1}\equiv 1\pmod p, ...
随机推荐
- Appium+python自动化(二十九)- 模拟手指在手机上多线多点作战 - 多点触控(超详解)
简介 在网页中我们经常使用缩放操作来便利的查看具体的信息,在appium中使用MultiAction多点触控的类来实现.MultiAction是多点触控的类,可以模拟用户多点操作.主要包含加载add( ...
- Unity的赛车游戏实现思路
unity目前版本实现赛车的技术方案主要有3种: 1.wheelCollider,设置motorTorque.brakeTorque.steerAngle来实现车子的推动和转弯,优点是上手简单,而且很 ...
- Maven安装配置及其插件m2e(Eclipse Indigo 和 MyEclipse8.5)的安装配置
Maven安装配置及其插件m2e(Eclipse Indigo 和 MyEclipse8.5)的安装配置 系统:Windows7 使用软件: Maven3.0.3 + Eclipse Indigo ...
- Markdown 基本语法(后面继续补充)
1.1 Markdown 基础语法 有序内容和无序内容 有序内容:输入1.然后按tab键 无序内容:输入' * ' 或 ' - ' 然后后按tab键 字体的样式 *** 内容 *** 加粗加斜(中间没 ...
- intellij idea与github整合管理代码
各位看官大家好,博主每每在公司学习新知识写代码时都需要通过U盘带回家来继续每天的学习,觉得这样实在麻烦,于是今天就整合了一下github来完成代码的管理. 开始之前我们需要准备三样东西:1.intel ...
- 实测win10 efi启动及centos7双系统引导顺序修改
安装win10 安装win10过程中,系统自动建立esp分区,分区格式为FAT16,目录如下 1,EFI/Boot文件夹保持不动 删除 EFI/Microsoft/boot/ 文件夹下面除BCD文件外 ...
- 昂贵的聘礼 POJ - 1062
题目链接:https://vjudge.net/problem/POJ-1062 如图,我们可以把交换的情况,抽象为一个有向图, 先抛去等级限制,那么就是一个最短路,从①出发,到达其他点的最短路中 最 ...
- 非常详细的Django使用Token(转)
基于Token的身份验证 在实现登录功能的时候,正常的B/S应用都会使用cookie+session的方式来做身份验证,后台直接向cookie中写数据,但是由于移动端的存在,移动端是没有cookie机 ...
- nginx单机1w并发优化
目录 ab工具 整体优化思路 具体的优化思路 编写脚本完成并发优化配置 性能统计工具 tips 总结 ab工具 ab -c 10000 -n 200000 http://localhost/index ...
- Selenium+java - 手把手一起搭建一个最简单自动化测试框架
写在前面 我们刚开始做自动化测试,可能写的代码都是基于原生写的代码,看起来特别不美观,而且感觉特别生硬. 来看下面一段代码,如下图所示: 从上面图片代码来看,具体特征如下: driver对象在测试类中 ...