(文前友情提醒:此篇博客略有些长,最近上得快,没太多时间更新)
暂无。
首先对于 L , R L,R L,R,非常的大,已知的所有筛法都无法在规定时间内求解。但是可以看到范围里还有很鬼畜的一条东西: R − L < = 1 0 6 R-L<=10^6 R−L<=106。根据它我们可以看出来,我们是可以扫描 L − R L-R L−R的。
考虑到一个合数K至少有一个小于等于 K \sqrt{K} K的因数,因此我们用线性筛筛出 R \sqrt{R} R的所有质数,将 L − R L-R L−R中所有该质数的倍数全部除去,最后再进行一边扫描,找题目的要求就可以了。
这里因为 L L L和 R R R比较大,我们可以映射到一个区域,来保证数组可以开下。
#include
using namespace std;
int read(){//快读
int s=0,w=0;
char ch=getchar();
for(;ch<'0'||ch>'9';ch=getchar())s|=ch=='-';
for(;ch>='0'&&ch<='9';ch=getchar())w=(w<<3)+(w<<1)+(ch^48);
return s?-w:w;
}
int L,R;
int vis[65537],pr[15001],tot,issp[1000001];
//vis数组表示一个数是否为质数
//pr数组则是记录具体的质数是哪些
//issp数组表示的是每次L和R区间哪些数是质数
void Prime(){
//筛法,此处使用了欧拉筛法
vis[1]=1;
for(int i=2;i<=65536;++i){
if(!vis[i]){
pr[++tot]=i;
}
for(int j=1;j<=tot;++j){
if(i*pr[j]>65536){
break;
}
vis[i*pr[j]]=1;
if(!i%pr[j]){
break;
}
}
}
return;
}
int shift(int l,int r,int prime){
//该函数用来计算一个质数的多少倍是第一个出现在L-R区间中的。
//返回的是它与L的距离(因为L,R较大,所以我们为了避免开大数组而采用了让所有下标减去L的方法来缩小范围)
long long x=((long long)l+(long long)prime-(long long)1)/(long long)prime;
long long y=x*prime-l+1;
return int(y);
}
int main(){
Prime();
int TT=0,Max,Maxi,Maxj,Min,Mini,Minj;
//设置TT是为了方便每次issp数组的使用,因为凉心出题人的存在而为了节约时间。对于每次修改issp就改为TT,查询改为是否是TT这也是竞赛中为了节约时间的常用方法。
//Max记录两个质数距离最大是多少,Min则记录两个质数距离最小是多少。
//Maxi,Maxj则为这两个质数是谁,Mini,Minj同理。
while(cin>>L){
++TT;
R=read();
if(L==1)issp[L]=TT;//emmm特判1
int lastpr=-1;
Max=-0x3f3f3f3f,Maxi=-1,Maxj=-1,Min=0x3f3f3f3f,Mini=-1,Minj=-1;
//这些是初始工作
for(int i=1;i<=tot;++i){
if(pr[i]*pr[i]>R){
break;
//质数是否出界
}
if(pr[i]<L){
for(int j=shift(L,R,pr[i]);j<=R-L+1;j+=pr[i])
issp[j]=TT;
//记录是否为质数,不是则为TT
}
else{
for(int j=int((long long)pr[i]*2-(long long)L+1);j<=R-L+1;j+=pr[i])
issp[j]=TT;
//同理
}
//此处分类讨论了,或许可以不讨论。
}
//这边是将非质数筛去。
for(int j=1;j<=R-L+1;++j){
if(issp[j]!=TT&&lastpr==-1){
lastpr=j;
//lastpr意为上一个质数。
}
else if(issp[j]!=TT&&lastpr!=-1){
if(j-lastpr>Max){
Max=j-lastpr;
Maxi=lastpr+L-1;
Maxj=j+L-1;
}
//找最大距离。
if(j-lastpr<Min){
Min=j-lastpr;
Mini=lastpr+L-1;
Minj=j+L-1;
}
//找最小距离。
lastpr=j;
//修改上一个质数。
}
}
//寻找最大距离和最小距离的过程
if(Maxi!=-1&&Maxj!=-1){
printf("%d,%d are closest, %d,%d are most distant.\n",Mini,Minj,Maxi,Maxj);
}
else{
puts("There are no adjacent primes.");
}
//输出即可。
}
return 0;
}
暂无。
范围香不香?所以你根本无法枚举,当然部分分是可以有的。
考虑一下2个数的 g c d ( x , y ) gcd(x,y) gcd(x,y),这等于一个质数。
质数? 1 0 7 10^7 107?我们知道是有筛法可以完成 1 s 1s 1s肝爆 1 0 7 10^7 107的,是不是意味着我们可以将它往素数那一方面想呢?
再考虑以下:设 g c d ( x , y ) = z gcd(x,y)=z gcd(x,y)=z,那么 g c d ( x z , y z ) gcd(\frac xz,\frac yz) gcd(zx,zy)是等于多少的呢?那就是 1 1 1了。
1 1 1?那么:假设y已经固定,那么对于 1 − y 1-y 1−y这个区间中,这样的 x x x有多少呢?无脑思考便可以得出结论: φ ( n ) φ(n) φ(n)个。
so?对于每个小于 n n n的质数,计算的便是 1 ≤ x , y ≤ n p 1\le x,y\le \frac np 1≤x,y≤pn中互质的 x , y x,y x,y。这样的对有多少个呢?对于每个 y y y,设 x ≤ y x\le y x≤y,那么便有 φ ( y ) ∗ 2 − 1 φ(y)*2-1 φ(y)∗2−1个(减 1 1 1是因为 x x x),所以我们可以做一遍前缀和,方便快速地计算。
至此,本题得到了解决。
#include
using namespace std;
int read(){//快读
int s=0,w=0;
char ch=getchar();
for(;ch<'0'||ch>'9';ch=getchar())s|=ch=='-';
for(;ch>='0'&&ch<='9';ch=getchar())w=(w<<3)+(w<<1)+(ch^48);
return s?-w:w;
}
int vis[10000001],prime[10000001],tot,phi[10000001],n;
//vis数组是用来记录该数字是否为质数。
//prime数组则是具体的质数是哪些。
//phi数组是欧拉函数。
long long s[10000001];
//这是前缀和数组。
int main(){
n=read();
for(int i=1;i<=n;++i)
phi[i]=i;
//初始工作。
for(int i=2;i<=n;++i){
if(!vis[i]){
vis[i]=i;
prime[++tot]=i;
phi[i]=i-1;
}
//这个是i是质数的情况。
for(int j=1;j<=tot;++j){
if(prime[j]>vis[i]||prime[j]>n/i){
break;
}
vis[i*prime[j]]=prime[j];
phi[i*prime[j]]=phi[i]*(i%prime[j]?prime[j]-1:prime[j]);
//根据欧拉函数的性质去快速计算。
}
}
//此处是欧拉筛法求欧拉函数。
for(int i=1;i<=n;++i)
s[i]=s[i-1]+(long long)phi[i];
//计算前缀和。
long long S=0;
for(int i=1;i<=tot;++i)
S+=s[n/prime[i]]*2-1;
//计算答案。
printf("%lld",S);
//输出。
return 0;
}
暂无。
先将它给的锑式转化。可以得到: x + k m ≡ y + k n ( m o d l ) x+km≡y+kn\pmod l x+km≡y+kn(modl)那么这个式子必然需要整治。所以我们开始魔改
x + k m ≡ y + k n ( m o d l ) → x − y + k ( m − n ) ≡ 0 ( m o d l ) → x+km≡y+kn\pmod l →x-y+k(m-n)≡0\pmod l → x+km≡y+kn(modl)→x−y+k(m−n)≡0(modl)→
k ( m − n ) − a ∗ l = y − x k(m-n)-a*l=y-x k(m−n)−a∗l=y−x
这已经很像不定方程了!
再次改进,我们设n-m为A,y-x为-B,那原式变为 k ∗ A + a ∗ l = B k*A+a*l=B k∗A+a∗l=B
这就可以使用扩欧解决。
但是请考虑一个问题,扩欧的式子: a ∗ x + b ∗ y = g c d ( a , b ) a*x+b*y=gcd(a,b) a∗x+b∗y=gcd(a,b),所以我们所求的只是一个特解。
那么所有解如何表示呢?
看:我们求得了一个 a ∗ x 0 + b ∗ y 0 = c a*x0+b*y0=c a∗x0+b∗y0=c,用这个式子减去最初的式子可以得到: a ∗ ( x − x 0 ) + b ∗ ( y − y 0 ) = 0 a*(x-x0)+b*(y-y0)=0 a∗(x−x0)+b∗(y−y0)=0
设 k = g c d ( a , b ) k=gcd(a,b) k=gcd(a,b)两边同除 k k k,这样可以使得新的 a , b a,b a,b互质,就可以得知: b k \frac bk kb| x − x 0 x-x0 x−x0的(或者 a k ∣ y 0 − y \frac ak|y0-y ka∣y0−y,这里我们考虑前面的)。所以我们便可以任意的去添加k而不会使得该等式不成立。所以最小的x0就是当x0与k互质时(即x0中不含k),那么便可得知方程的最小解。但是上面的式子右边是 g c d ( a , b ) gcd(a,b) gcd(a,b),设 S = g c d ( a , b ) S=gcd(a,b) S=gcd(a,b),则结果需要乘上 b S \frac bS Sb。
#include
using namespace std;
long long read(){
long long s=0,w=0;
char ch=getchar();
for(;ch<'0'||ch>'9';ch=getchar())s|=ch=='-';
for(;ch>='0'&&ch<='9';ch=getchar())w=(w<<3)+(w<<1)+(ch^48);
return s?-w:w;
}
long long n,m,x,y,l,s,X1,Y1;
//前五个为读入的对应变量,后面的X1,Y1为exgcd的解。
long long exgcd(long long a,long long b,long long &X1,long long &Y1){
//exgcd求出k。
if(!b){
X1=1;
Y1=0;
return a;
}
s=exgcd(b,a%b,X1,Y1);
long long New=X1;
X1=Y1;
Y1=New-a/b*Y1;
return s;
}
int main(){
x=read(),y=read(),m=read(),n=read(),l=read();
//读入。
y=x-y,x=n-m;
//这是A和B。
if(x<0)x=-x,y=-y;
//考虑负数。
exgcd(x,l,X1,Y1);
//求k。
if(y%s)puts("Impossible");
//讨论是否有解。
else cout<<((X1*(y/s))%(l/s)+(l/s))%(l/s);
//输出最小解。
return 0;
}
暂无。
暂无。
暂无。
矩阵乘法是对于两个矩阵之前的操作。
设 A A A为 n ∗ x n*x n∗x的矩阵, B B B为 x ∗ m x*m x∗m的矩阵。 C C C为结果矩阵,则 C C C为一个 n ∗ m n*m n∗m的矩阵。
且 ∀ i ∈ [ 1 , n ] , ∀ j ∈ [ 1 , x ] \forall i\in[1,n],\forall j\in[1,x] ∀i∈[1,n],∀j∈[1,x]: C i , j C_{i,j} Ci,j= ∑ k = 1 m A i , k ∗ B k , j \sum_{k=1}^m A_{i,k}*B_{k,j} ∑k=1mAi,k∗Bk,j。
对了,矩阵乘法有什么性质呢?
它具有结合律,即 ( A × B ) × C = A × ( B × C ) (A\times B)\times C=A\times (B\times C) (A×B)×C=A×(B×C)
它具有乘法左分配率,即 ( A + B ) × C = A × C + B × C (A+B)\times C=A\times C+B\times C (A+B)×C=A×C+B×C
它具有乘法右分配率,即 C × ( A + B ) = C × A + C × B C\times (A+B)=C\times A+C\times B C×(A+B)=C×A+C×B
它也具有对数乘的结合性,即 c × A × B = A × ( c × B ) c\times A\times B=A\times (c\times B) c×A×B=A×(c×B)
它也可以转置,即 ( A × B ) K = A K × B K (A\times B)^K=A^K\times B^K (A×B)K=AK×BK
但是它不满足交换率,即 A × B = ̸ B × A A\times B=\not B\times A A×B≠B×A
为什么呢?考虑到上面的式子,新的矩阵的每个位置得到的方法是左边矩阵的行乘以右边矩阵的列。当两个矩阵调换位置之后,结果自然就不同了。
或许很多人有疑问了:这个矩阵乘法有什么用呢?其实它非常有用。毕竟它可以加速递推。下面我们根据一道题来了解一下它的用处。
这题就是让你推斐波那契第n项,但是n非常大,在long long范围内,直接递推显然会让你痛不欲生,我们可以考虑矩阵。
观察斐波那契递推式: f ( n ) = f ( n − 1 ) + f ( n − 2 ) f(n)=f(n-1)+f(n-2) f(n)=f(n−1)+f(n−2),考虑到一个数只与后两个数有关,所以我们开一个小小的数组 a [ 3 ] a[3] a[3], a [ 1 ] = a [ 2 ] = 1 a[1]=a[2]=1 a[1]=a[2]=1,之后我们要推出 a [ 2 ] , a [ 3 ] a[2],a[3] a[2],a[3],首先 a [ 2 ] a[2] a[2]是有的, a [ 3 ] = a [ 2 ] + a [ 1 ] a[3]=a[2]+a[1] a[3]=a[2]+a[1],因此我们可以开一个二维矩阵来递推。这个矩阵是这样的:
k [ 2 ] [ 2 ] k[2][2] k[2][2]= [ 0 1 1 1 ] \begin{bmatrix}0&1\\1&1\end{bmatrix} [0111]
因此,我们如果需要 f ( n ) f(n) f(n),即 a [ n ] a[n] a[n]的第一个数, a [ n ] = a [ n − 1 ] × k = a [ n − 2 ] × k × k … a[n]=a[n-1]\times k=a[n-2]\times k\times k\dots a[n]=a[n−1]×k=a[n−2]×k×k…
得到 a [ n ] = a [ 1 ] × k n − 1 a[n]=a[1]\times k^{n-1} a[n]=a[1]×kn−1,所以呢,我们可以运用快速幂飞快的计算出解。
记得我旁边某位大佬说过:快的不是矩阵乘法,快的是快速幂。其实矩阵乘法之所以可以优化递推,就是因为它具有结合律。
下贴代码:
#include
using namespace std;
#define mod 1000000007;
//本题模数。
long long n,a[3]={0,1,1},A[3][3]={{0,0,0},{0,0,1},{0,1,1}};
//a数组为存着的两个斐波那契数。
//A数组为矩阵。
void mulself(){
long long c[3][3];
memset(c,0,sizeof(c));
for(int i=1;i<=2;i++)
for(int j=1;j<=2;j++)
for(int k=1;k<=2;k++)
c[i][j]=(c[i][j]+A[i][k]*A[k][j])%mod;
memcpy(A,c,sizeof(c));
}
//让A矩阵乘以A矩阵。
void mul(){
long long c[3];
memset(c,0,sizeof(c));
for(int i=1;i<=2;i++)
for(int j=1;j<=2;j++)
c[i]=(c[i]+a[j]*A[j][i])%mod;
memcpy(a,c,sizeof(c));
}
//让a数组乘以A矩阵。
int main(){
cin>>n;--n;
//执行n-1次。
for(;n;n>>=1,mulself())if(n&1)mul();
//快速幂。
cout<<a[1];
//输出。
return 0;
}
其实矩阵并不难,熟能生巧吧。
暂无。
我知道这个要高斯消元,现在还没更高斯消元会有些**,凑合一下吧。(会尽早更的啦)。
一般的算法竞赛书上写的有关的介绍都有一些emmm,还是写一下吧:
1.向量加法 a + b a+b a+b,其中 a , b a,b a,b均为向量。
2.标量乘法 k × a k\times a k×a,也称数乘运算,其中 a a a是向量, k k k是常数(标量)
--算法进阶指南
完了,这个也需要一些日子才能更了,又咕了QAQ
tm上面还没更完。。。
先更这个吧,毕竟这个还有一些把握。。。
先说一下两个重要的原理:
加法原理:如果完成一件事情有 n n n 类,其中第 i i i 类有 a [ i ] a[i] a[i] 种方法,并且这些方法互不重合,那么完成事情的方案数共 ∑ i = 1 n a [ i ] \sum_{i=1}^na[i] ∑i=1na[i]种。
乘法原理:如果完成一件事情有 n n n 步,其中第 i i i 步有 a [ i ] a[i] a[i] 种方法,并且这些方法互不重合,那么完成事情的方案数共 ∏ i = 1 n a [ i ] \prod_{i=1}^na[i] ∏i=1na[i]种。
或许您会认为这十分简单,但是当您在做数学(雾)的时候,你会发现你认为对的都错了。本蒟蒻深有体会。(350分拿140)
接下来再介绍两个东西:
考虑到我们取出 m m m 个数后,剩下的 n − m n-m n−m 个数也组成了一个集合,所以对于所有的方案,都有一个 n − m n-m n−m 个元素的集合与之对应,故 C n m = C n n − m C_n^m=C_n^{n-m} Cnm=Cnn−m
我们在 n n n 个数中取 m m m 个,当我们在考虑是否选取第 n n n 个的时候,方案数等于选到了第 n − 1 n-1 n−1 个的时候剩下了一个位置给第n个元素 + + + 我们选到了第 n − 1 n-1 n−1 个的时候没剩下位置给第n个元素。即 C n m = C n − 1 m + C n − 1 m − 1 C_n^m=C_{n-1}^m+C_{n-1}^{m-1} Cnm=Cn−1m+Cn−1m−1
∑ i = 1 n C n i \sum_{i=1}^nC_n^i ∑i=1nCni即为在n个元素的集合里选取随意多的数,换个思路,就是每个元素可以选择或者不选择,答案即为 2 n 2^n 2n 个,故 ∑ i = 1 n C n i = 2 n \sum_{i=1}^nC_n^i=2^n ∑i=1nCni=2n
这便是以上三条性质的证明。
现在我们讨论讨论组合数的求法,看第二条性质不难想到利用递推,为了避免爆炸,我们可以用质因数相减思路。
因此有了二项式定理。
矩阵形式: ( a + b ) n = [ a 0 … a n ] × [ C n 0 ⋱ C n n ] × [ 1 ⋮ 1 ] × [ b 0 ⋮ b n ] (a+b)^n=\begin{bmatrix}a^0&\dots& a^n\end{bmatrix}\times \begin{bmatrix}C_n^0\\&\ddots&\\& &C_n^n\end{bmatrix}\times \begin{bmatrix}& & 1\\& \vdots\\1\end{bmatrix}\times \begin{bmatrix}b^0\\\vdots\\b^n\end{bmatrix} (a+b)n=[a0…an]×⎣⎡Cn0⋱Cnn⎦⎤×⎣⎢⎡1⋮1⎦⎥⎤×⎣⎢⎡b0⋮bn⎦⎥⎤, n ∈ N + n\in\N^+ n∈N+
当 n = 1 n=1 n=1 时, ( a + b ) 1 = C n 0 × a 0 × b n − k = a + b (a+b)^1=C_n^0\times a^0\times b^{n-k}=a+b (a+b)1=Cn0×a0×bn−k=a+b成立。
假设当 n = m n=m n=m时命题成立,设 n = m + 1 n=m+1 n=m+1,则有:
( a + b ) m + 1 (a+b)^{m+1} (a+b)m+1
= a ( a + b ) m + b ( a + b ) m a(a+b)^m+b(a+b)^m a(a+b)m+b(a+b)m
= ( a + b ) ∑ k = 0 m C m k × a k × b m − k (a+b)\sum_{k=0}^mC_m^k\times a^k\times b^{m-k} (a+b)∑k=0mCmk×ak×bm−k
= ∑ k = 0 m C m k × a k + 1 × b m − k + ∑ k = 0 m C m k × a k × b m − k + 1 \sum_{k=0}^mC_m^k\times a^{k+1}\times b^{m-k}+\sum_{k=0}^mC_m^k\times a^k\times b^{m-k+1} ∑k=0mCmk×ak+1×bm−k+∑k=0mCmk×ak×bm−k+1
= ∑ k = 1 m + 1 C m k − 1 × a k × b m − k + 1 + ∑ k = 0 m C m k × a k × b m − k + 1 \sum_{k=1}^{m+1}C_m^{k-1}\times a^k\times b^{m-k+1}+\sum_{k=0}^mC_m^k\times a^k\times b^{m-k+1} ∑k=1m+1Cmk−1×ak×bm−k+1+∑k=0mCmk×ak×bm−k+1
= ∑ k = 0 m + 1 ( C m k − 1 + C m k ) × a k × b m − k + 1 \sum_{k=0}^{m+1}(C_m^{k-1}+C_m^k)\times a^k\times b^{m-k+1} ∑k=0m+1(Cmk−1+Cmk)×ak×bm−k+1
= ∑ k = 0 m + 1 C m + 1 k × a k × b m + 1 − k \sum_{k=0}^{m+1}C_{m+1}^k\times a^k\times b^{m+1-k} ∑k=0m+1Cm+1k×ak×bm+1−k
证毕。
现在就去尝试一下这个吧!
这题题目简洁明了,给一个多项式 ( a x + b y ) k (ax+by)^k (ax+by)k,求多项式展开后 x n × y m x^n\times y^m xn×ym项的系数,对10007取模。
范围: 0 ≤ n , m ≤ k ≤ 1000 , n + m = k , 0 ≤ a , b ≤ 1 0 6 0\le n,m\le k\le1000,n+m=k,0\le a,b\le 10^6 0≤n,m≤k≤1000,n+m=k,0≤a,b≤106。
其实就是一道简简单单的题,考据二项式定理,就可以知道 x n × y m x^n\times y^m xn×ym 的系数是 C k n × a n × b m C_k^n\times a^n\times b^m Ckn×an×bm ,然后就可以直接计算了,对于中间的除法直接利用逆元即可。
下贴代码:
#include
using namespace std;
#define mod 10007
long long a,b,k,n,m,S;
//模数,题目中对应的变量。
long long ksm(long long x,long long y,long long z=1){
for(;y;y>>=1,x=x*x%mod)if(y&1)z=z*x%mod;
return z;
}
//快速幂
long long C(long long x,long long y){
long long s=1;
for(long long i=1;i<=x;++i)
s=s*i%mod;
//计算分子。
long long s1=1;
for(long long i=1;i<=y;++i)
s1=s1*i%mod;
for(long long i=1;i<=x-y;++i)
s1=s1*i%mod;
//计算分母的积。
s=s*ksm(s1,mod-2)%mod;
//对分母的积统一求逆元,计算答案。
return s;
}
//计算组合数
int main(){
scanf("%lld %lld %lld %lld %lld",&a,&b,&k,&n,&m);
//读入。
S=ksm(a,n)*ksm(b,m)%mod;
S=S*C(k,n)%mod;
//计算答案。
printf("%lld",S);
return 0;
}
首先我们需要证明三个结论。
证明:
C p i = p ! i ! × ( p − i ) ! = p i × ( p − 1 ) ! ( i − 1 ) ! × ( p − i ) ! = p i C p − 1 i − 1 C_p^i=\dfrac {p!}{i!\times (p-i)!}=\dfrac pi\times \dfrac {(p-1)!}{(i-1)!\times (p-i)!}=\dfrac piC_{p-1}^{i-1} Cpi=i!×(p−i)!p!=ip×(i−1)!×(p−i)!(p−1)!=ipCp−1i−1
观察 C p i = p ! i ! × ( p − i ) ! C_p^i=\dfrac {p!}{i!\times(p-i)!} Cpi=i!×(p−i)!p!,考虑到 i ! × ( p − i ) ! i!\times (p-i)! i!×(p−i)!,这两个数都比 p p p 小,由于 p p p 是质数,故该式子中仅
有分子有p这个因子,故 C p i ≡ p i C p − 1 i − 1 ≡ 0 ( m o d p ) C_p^i\equiv \dfrac piC_{p-1}^{i-1}\equiv0\pmod p Cpi≡ipCp−1i−1≡0(modp)
( 1 + x ) p = ∑ k = 0 p C n k × a k × b p − k (1+x)^p=\sum_{k=0}^pC_n^k\times a^k\times b^{p-k} (1+x)p=∑k=0pCnk×ak×bp−k
为了方便观察这边将它改为繁琐些的式子。
( 1 + x ) p ~~~~(1+x)^p (1+x)p
= C p 0 × x 0 × 1 p + C p − 1 1 × x 1 × 1 p − 1 + … + C p p × x n × 1 0 =C_p^0\times x^0\times 1^p+C_{p-1}^1\times x^1\times 1^{p-1}+~~\dots~~+C_p^p\times x^n\times 1^0 =Cp0×x0×1p+Cp−11×x1×1p−1+ … +Cpp×xn×10
根据上面的结论 1 1 1 ,我们可以得知,仅有 C p 0 × x 0 × 1 p + C p p × x n × 1 0 C_p^0\times x^0\times 1^p+C_p^p\times x^n\times 1^0 Cp0×x0×1p+Cpp×xn×10是有效的,故原式
≡ C p 0 × x 0 × 1 p + C p p × x n × 1 0 ( m o d p ) \equiv C_p^0\times x^0\times 1^p+C_p^p\times x^n\times 1^0\pmod p ≡Cp0×x0×1p+Cpp×xn×10(modp)
≡ 1 + x p \equiv 1+x^p ≡1+xp
有了以上两个结论,再来证明第三个就非常简单。
∵ ( 1 + x ) z = ( 1 + x ) a p × ( 1 + x ) b \because(1+x)^z=(1+x)^{ap}\times (1+x)^b ∵(1+x)z=(1+x)ap×(1+x)b
( 1 + x ) a p ≡ ( ( 1 + x ) p ) a ≡ ( 1 + x p ) a (1+x)^{ap}\equiv((1+x)^p)^a\equiv(1+x^p)^a (1+x)ap≡((1+x)p)a≡(1+xp)a
∴ ( 1 + x ) z ≡ ( 1 + x p ) a × ( 1 + x ) b \therefore(1+x)^z\equiv(1+x^p)^a\times (1+x)^b ∴(1+x)z≡(1+xp)a×(1+x)b
我们接着往下探索:
设一个数 n = i p + j n=ip+j n=ip+j,
C a n × x n C_a^n\times x^n Can×xn有什么方法改的好看一些呢 q w q qwq qwq
其实有,只不过更丑了 。
考虑到我们已经知道了 ( 1 + x ) z ≡ ( 1 + x p ) a × ( 1 + x ) b ( m o d p ) (1+x)^z\equiv(1+x^p)^a\times (1+x)^b\pmod p (1+x)z≡(1+xp)a×(1+x)b(modp),大力提出两边式子里n的系数,可以发现左边为 C a n C_a^n Can ,右边则为 C a i × C b j C_a^i\times C_b^j Cai×Cbj,为什么呢?因为 b b b 是由一个数   m o d   p \bmod~p mod p得来的,那么 b ≤ q − 1 b\le q-1 b≤q−1,所以为了让两边系数相等, i × p i\times p i×p这个系数必须去 ( 1 + x p ) a (1+x^p)^a (1+xp)a里面找,而 j j j 这个系数则必须去 ( 1 + x ) b (1+x)^b (1+x)b里找。
所以
C a n × x n ≡ C a i × x i × p × C b j × x j C_a^n\times x^n\equiv C_a^i\times x^{i\times p}\times C_b^j\times x^j Can×xn≡Cai×xi×p×Cbj×xj。
C a n × x n ≡ C a i × C b j × x n C_a^n\times x^n\equiv C_a^i\times C_b^j\times x^n Can×xn≡Cai×Cbj×xn
C a n ≡ C a i × C b j C_a^n\equiv C_a^i\times C_b^j Can≡Cai×Cbj
或许证完了。
又得等一段时间???
又很开心了 q w q qwq qwq ,没更容斥先更莫比。。。
莫比乌斯反演是数论数学中很重要的内容,可以用于解决很多组合数学的问题。
–百度百科
一开始比较迷(虽然现在也是。。。),但是题目做多了,套路感觉就来了。
首先查了一下莫比乌斯反演,那些百科上面对莫比乌斯反演的介绍真是面(又)面(臭)俱(又)到(长)。
首先我们引入莫比乌斯函数μ
它的定义是这样的: