zoukankan      html  css  js  c++  java
  • qbxt五一数学Day2

    1. 判断素数(素性测试)

    1. (O(sqrt n)) 试除

    bool isprime(int n)
    {
    	if (n<2) return false;
    	for (int i=2;i*i<=n;i++)
    		if (!(n%i)) return false;
    	return true;
    }
    

    2. Miller-Rabin 素性测试

    Theorm 1

    (n) 是素数,则对于任意 (1le ale n),设 (n-1=dcdot 2^r),则

    [a^dequiv 1pmod n;,;{large exists}_{0le ile r}\,a^{dcdot 2^i}equiv -1pmod n ]

    中至少有一个成立 .

    随便找若干个数 (a) 进行判定,很大概率对(4~8 个在 long long 范围稳了)(取质数效果较好)

    时间复杂度 (O(klog^2 n))

    const int PrimeList[]={2,3,5,11,37,43,67,73,97}; // for Miller-Rabin
    ll qmul(ll a,ll n,ll P)
    {
    	ll ans=0; if (!n) return 0;
    	while (n)
    	{
    		if (n&1) ans=(ans+a)%P;
        	n>>=1; a=(a+a)%P;
    	} return ans%P;
    }
    ll qpow(ll a,ll n,ll P)
    {
    	ll ans=1;
    	while (n)
    	{
    		if (n&1) ans=qmul(ans,a,P)%P;
    		n>>=1; a=qmul(a,a,P)%P;
    	} return ans;
    }
    bool miller_rabin(ll n,int a)
    {
    	ll d=n-1,r=0;
    	while (!(d&1)){++r; d>>=1;}
    	ll x=qpow(a,d,n);
    	if (x==1) return true;
    	for (int i=0;i<r;i++)
    	{
    		if (x==n-1) return true;
    		x=qmul(x,x,n)%n;
    	} return false;
    }
    bool MillerRabin(ll n)
    {
    	if (n<2) return false;
    	for (int i=0;i<9;i++)
    	{
    		if (n==PrimeList[i]) return true;
    		if (n%PrimeList[i]==0) return false;
    		if (!miller_rabin(n,PrimeList[i])) return false;
    	} return true;
    }
    

    * 欧拉函数

    定义:

    (varphi(n)) 定义为 (1sim n) 中与 (n) 互质的数的个数,即:

    [varphi(n)=sum_{i=1}^n[gcd(i,n)=1] ]

    Theorm *

    欧拉函数的求值公式:

    [varphi(n)=nleft(1-dfrac 1{p_1} ight)left(1-dfrac 1{p_2} ight)cdotsleft(1-dfrac 1{p_r} ight)mathrm{\,where;} n=prod_{i=1}^r p_i^{alpha_i} ]

    Proof:容斥原理

    [ ag*{□} ]

    公式求 (varphi) 值:

    ll phi(ll n) // O(sqrt(n))
    {
    	ll ans=n;
    	for (int i=2;i*i<=n;i++)
    		if (!(n%i))
    		{
    			ans=ans/i*(i-1);
    			while (!(n%i)) n/=i;
    		}
    	if (n>1) ans=ans/n*(n-1);
    	return ans;
    }
    

    Theorm *(欧拉函数是积性函数)

    (n,m) 互质,则 (varphi(n)varphi(m)=varphi(nm)) .

    Proof:由求值式子显然得证 .

    [ ag*{□} ]

    2. 逆元

    定义:

    (b) 使得 (abequiv 1pmod m),则 (b) 成为 (a)(m) 意义下的逆元,记作 (b=a^{-1}) .

    Theorm 2
    逆元存在的充要条件是 (gcd(a,m)=1) .

    我们知道费马小定理和欧拉定理:

    Theorm 3(费马小定理)

    对于 (gcd(a,p)=1)(p) 为质数,有:

    [a^{p-1}equiv 1pmod p ]

    Theorm 4(欧拉定理)

    对于 (gcd(a,p)=1),有:

    [a^{varphi(p)}equiv 1pmod p ]

    其中 (varphi) 是欧拉函数 .

    素数求逆元:用费马小定理,答案是 (a^{-1}=a^{p-2}) .

    其他:

    1. 用欧拉定理,答案是 (a^{-1}=a^{varphi(p)-1}) .
    2. 用 exgcd,问题等价于求解 (ax+by=p) .

    (1sim n) 的逆元:

    预处理阶乘,阶乘逆元可以

    [(n-1)!^{-1}=n!^{-1}n ]

    求,(n) 的逆元可以

    [n^{-1}=n!^{-1}(n-1)! ]

    求 .

    3. exgcd(扩展欧几里得)

    求解不定方程

    [ax+by=c ]

    其中 (x,y) 是整数 .

    Theorm 5(裴蜀定理 / 贝祖定理)

    [ax+by=c ]

    有解当且仅当 (gcd(a,b)mid c) .

    所以只需要处理 (ax+by=gcd(a,b)) 的解即可 .

    注意到 (gcd(a,b)=gcd(b,amod b)),设 (G=gcd(a,b)) .

    我们按照欧几里德算法(即辗转相除法),当 (b=0) 时,容易发现 (x=1,y=0) .

    若不然,如果我们知道

    [bx_0+(amod b)y_0=G ]

    的解,我们就可以依照如下方法求 (ax+by=G) 的解:

    [egin{aligned}bx_0+(amod b)y_0&=bx_0+left(a-bleftlfloordfrac ab ight floor ight)y_0\&=ay_0+bleft(x_0-y_0leftlfloordfrac ab ight floor ight)end{aligned} ]

    int ex_gcd(int a,int b,int& x,int& y)
    {
    	if (!b){x=1; y=0; return a;}
    	int xp,yp,g=ex_gcd(b,a%b,xp,yp);
    	x=yp; y=xp-yp*(a/b); return g;
    	return 0;
    }
    

    4. 离散对数(BSGS 算法求解)

    BSGS:大步小步算法北上广深·百事公司·阿姆斯特朗算法

    求解同余方程

    [a^xequiv bpmod p ]

    其中 (p) 是质数 .

    由费马小定理,这个 (x) 不会超过 (p-1) .

    分成如下数表:

    如图,将所有行转换到第一行,用一个 sethash 维护即可 .

    ll BSGS(ll a,ll b,ll p) // a^x=b (mod p)
    {
    	int s=sqrt(p),x=1; set<int> se;
    	for (int i=0;i<s;i++){se.insert(x); x=1ll*x*a%p;}
    	int y=qpow(qpow(a,s,p),p-2,p),z=b;
    	for (int i=1;;i++)
    	{
    		if (se.count(z))
    		{
    			z=qpow(a,(i-1)*s,p);
    			for (int j=(i-1)*s;;j++)
    				if (z==b) return j;
    				else z=1ll*z*a%p;
    		} z=1ll*z*y%p;
    	}
    } // 要判无解只需要判断循环次数是否过多即可 .
    

    5. CRT(中国剩余定理)

    考虑合并两个方程,

    [egin{cases}xequiv b_1pmod{p_1}\xequiv b_2pmod{p_2}end{cases} ]

    法一:大数翻倍法(zhx 的神仙解法)

    枚举 (b_1,b_1+p_1,b_1+2p_1,cdots) 判断是否成立

    static pair<ll,ll> MergeEqu(ll a1,ll m1,ll a2,ll m2)
    {
    	if (m2>m1) swap(m1,m2),swap(a1,a2);
    	while (a1%m2!=a2) a1+=m1;
    	return make_pair(a1,lcm(m1,m2));
    }
    

    法二:用扩展欧几里得解

    (x=k_1p_1+b_1=k_2p_2+b_2),则

    [k_1p_1-k_2p_2=b_2-b_1 ]

    则:

    [dfrac{p_1}{gcd(p_1,p_2)}equiv dfrac{b_2-b_1}{gcd(p_1,p_2)}left(mod {dfrac{p_2}{gcd(p_1,p_2)}} ight) ]

    用扩欧解出 (k_1) 即可 .

    6. 线性筛(xxs)

    1. 筛素数

    碍事筛埃氏筛:

    notprime[1]=true;
    for (int i=2;i<=n;i++)
    {
    	if (notprime[i]) continue;
    	for (int j=i+i;j<=n;j++) notprime[j]=true;
    }
    

    这是对于每个素数 (i) 枚举它的所有倍数筛掉

    我们反过来,用每个数 (i) 枚举它的所有素数倍:

    vector<int> plist; notprime[1]=true;
    for (int i=2;i<=n;i++)
    {
    	if (!notprime[i]) plist.push_back(i);
    	for (auto x:plist)
    	{
    		int now=i*x;
    		if (now>n) break;
    		notprime[x]=true;
    	}
    } // C++11
    
    /* 数组写法  */
    
    notprime[1]=true;
    for (int i=2;i<=n;i++)
    {
    	if (!notprime[i]) plist[++pcnt]=i;
    	for (int j=1;j<=pcnt;j++)
    	{
    		int now=i*plist[j];
    		if (now>n) break;
    		notprime[plist[j]]=true;
    	}
    }
    

    注意到每个数可能被筛多次,例如:

    [12=2 imes 6=3 imes 4 ]

    翻过来后就是枚举到 (4,6) 时,找到 (2,3) 筛掉 (12) .

    我们希望每个数只被它的最小质因子筛掉 .

    我们进行模拟:

    当我们发现 (4) 时,枚举:

    • 素数 (2):筛掉 (8) .
    • 素数 (3):注意到 (2)(上一个素数)是 (4) 的倍数,所以后面的素数都不用枚举了,因为不是最小素因子(此处最小素因子至多是 (2)

    用这种想法写出最终代码:

    vector<int> plist; notprime[1]=true;
    for (int i=2;i<=n;i++)
    {
    	if (!notprime[i]) plist.push_back(i);
    	for (auto x:plist)
    	{
    		int now=i*x;
    		if (now>n) break;
    		notprime[x]=true;
    		if (!(i%x)) break;
    	}
    }
    

    2. 筛积性函数((varphi)(mu)

    (k) 是素数时:

    [varphi(k)=k-1;,;mu(k)=-1 ]

    当第 (10) 行成立,显然 (mu(now)=0) .

    因为没有其他增加的素因子,由欧拉函数计算式得 (varphi(now)=xcdotvarphi(x)) .

    如果互素(即第 (11) 行成立),由积性显然有 (varphi(now)=varphi(x)varphi(i))(mu(now)=mu(x)mu(i))

    在板子上改一改就行辣

    notprime[1]=true; phi[1]=mu[1]=1;
    for (int i=2;i<=n;i++)
    {
    	if (!notprime[i]){plist.push_back(i); phi[i]=i-1; mu[i]=-1;}
    	for (auto x:plist)
    	{
    		int now=i*x;
    		if (now>n) break;
    		notprime[now]=true;
    		if (!(i%x)){phi[now]=phi[i]*x; mu[now]=0; break;}
    		else{phi[now]=phi[i]*phi[x]; mu[now]=mu[i]*mu[x];}
    	}
    }
    

    7. 数论函数与狄利克雷卷积

    1. (mu)

    1. 定义与性质

    (mu):莫比乌斯函数 ,数论容斥函数 .

    定义:

    对于整数 (n),定义:

    [mu(n)=egin{cases}1&n=1\(-1)^r&{largeforall}_{iin[1,r]cap mathbb Z}:alpha_i=1\0& m otherwise.end{cases}mathrm{\,where;} n=prod_{i=1}^r p_i^{alpha_i} ]

    Theorm:对于 (nperp m),有 (mu(nm)=mu(n)mu(m))(mu) 是积性函数 .

    Proof:

    [n=prod_{i=1}^r p_i^{alpha_i};,;m=prod_{i=1}^t q_i^{eta_i} ]

    其中 ({large forall}_{iin[1,r]cap mathbb Z\,,\,jin[1,t]cap mathbb Z}:p_i eq q_j)(即 (n,m) 互质).

    (alpha_i=eta_j=1) 时(其余情况易证),

    [mu(nm)=muleft(prod_{i=1}^r p_i^{alpha_i}cdot prod_{i=1}^t q_i^{eta_i} ight)=(-1)^{r+t}=(-1)^r(-1)^t=mu(n)mu(m) ag*{⬜} ]

    2. 例题

    问在 (1)(n) 中有多少个数可以表示为

    [t=x^y ]

    其中 (xge 1,yge 2) .
    数据范围:(nle 10^{18})

    对于对于一个 (y),存在 (sqrt[y]n)(x) 满足条件(显然有 (yle log_2 (10^{18})),即 (yle 64)).

    注意到有数会重复,e.g.

    [64=8^2=4^3=2^6 ]

    答案即为:

    [sum_{i=2}^{64}-mu(i)(sqrt[i]n-1)+1 ]

    (这个 (-1) (+1) 是为了去掉 (1=1^?)
    暴力求即可 .

    2. 狄利克雷卷积

    1. 定义

    数论卷积(或狄利克雷(Dirichlet)卷积):

    对于数论函数 (f,g),定义他们的狄利克雷卷积为:

    [(f*g)(n)=sum_{dmid n}f(d)gleft(dfrac nd ight) ]

    注:(sumlimits_{dmid n}) 是枚举因子 .

    有性质:

    • 交换律:(f*g=g*f) .
    • 结合律:((f*g)*h=f*(g*h))
    • 分配律:((f+g)*h=f*h+g*h)

    2. 特殊函数的狄利克雷卷积

    [mu*I=varepsilon ]

    其中 (I(n)=1\,,\,varepsilon(n)=[n=1]) .

    即对于 (n>1),有:

    [sum_{dmid n}mu(d)=0 ]

    [varphi*I=id ]

    其中 (id(n)=n) .

    即:

    [sum_{dmid n}varphi(d)=n ]

    [mu*id=varphi ]

    Proof:

    [egin{aligned}mu* id&=mu*varphi*I\&=mu*I*varphi\&=varepsilon*varphi\&=varphiend{aligned} ]

    3. 例题

    求和变形技巧:

    1. 增加枚举变量
    2. 交换枚举顺序
    3. 删除无用变量

    Problem 1

    给定 (n,m),求:

    [sum_{i=1}^nsum_{j=1}^mgcd(i,j) ]

    [egin{aligned}sum_{i=1}^nsum_{j=1}^mgcd(i,j)&=sum_{i=1}^nsum_{j=1}^mid(gcd(i,j))\&=sum_{i=1}^nsum_{j=1}^msum_{dmidgcd(i,j)}varphi(d)& ext{(增加枚举变量)}\&=sum_{d=1}^nsum_{i=1}^{leftlfloorfrac nd ight floor}sum_{i=1}^{leftlfloorfrac md ight floor}varphi(d)& ext{(交换枚举顺序)}\&=sum_{d=1}^nleftlfloordfrac nd ight floorleftlfloordfrac md ight floorvarphi(d)& ext{(删除无用变量)}end{aligned} ]

    (第三个等号是把 (gcd) 转换成枚举倍数).

    然后预处理 (varphi),时间复杂度 (O(n)) .

    Problem 2

    给定 (n),问存在多少 (1le i,jle n),使得 (i,j) 互质 .

    显然题目让求的是:

    [egin{aligned}sum_{i=1}^nsum_{j=1}^nvarepsilon(gcd(i,j))&=sum_{i=1}^nsum_{j=1}^msum_{dmidgcd(i,j)}mu(d)& ext{(增加枚举变量)}\&=sum_{d=1}^nsum_{i=1}^{leftlfloorfrac nd ight floor}sum_{i=1}^{leftlfloorfrac md ight floor}mu(d)& ext{(交换枚举顺序)}\&=sum_{d=1}^nleftlfloordfrac nd ight floorleftlfloordfrac md ight floormu(d)& ext{(删除无用变量)}end{aligned} ]

    和上一题几乎一样 [表情]

    3. 莫比乌斯反演

    [g(n)=sum_{dmid n}f(d);Leftrightarrow;f(x)=sum_{dmid n}mu(d)gleft(dfrac nd ight) ]

    [g=f*I;Leftrightarrow;f=mu*g ]

    Proof:

    [egin{aligned}g=f*I&Leftrightarrow mu*g=f*I*mu\&Leftrightarrow mu*g=f*varepsilon\&Leftrightarrow mu*g=fend{aligned} ]

    [ ag*{⬜} ]

    8. 计数

    1. 计数原理

    1. 加法原理

    一件事若干类(并列),方案数加起来

    2. 乘法原理

    一件事若干步(递进),方案数乘起来

    2. 排列组合

    定义

    组合:(n) 中无序选 (r)

    [C(n,r)=dbinom{n}{r}=dfrac{n!}{r!(n-r)!} ]

    排列:(n) 中有序选 (r)

    [P(n,r)=A(n,r)=n^{underline{r}}=dfrac{n!}{(n-r)!} ]

    性质

    [dbinom{n+m}{n}=dbinom{n+m}{m} ]

    组合意义:选不选的

    [dbinom{n}{m}=dbinom{n-1}{m-1}+dbinom{n-1}{m} ]

    组合意义:第一件选不选

    [dbinom{n+r+1}{r}=dbinom{n+r}{r}+dbinom{n+r-1}{r-1}+cdots+dbinom{n}{0}=sum_{i=0}^rdbinom{n-r-i}{r-i} ]

    反复用前面那个式子

    [dbinom{n}{l}dbinom{l}{r}=dbinom{n}{r}dbinom{n-r}{l-r} ]

    组合意义:选两次

    [dbinom{n}{0}+dbinom{n}{1}+cdots+dbinom{n}{n}=2^n ]

    组合意义:取数用乘法原理、组合数两种算法

    [dbinom{n}{0}-dbinom{n}{1}+dbinom{n}{2}-cdots=0 ]

    组合意义:建立奇数项与偶数项的一一对应,以达成消去的效果(第一项取反) .

    [dbinom{r}{r}+dbinom{r+1}{r}+cdots+dbinom{n}{r}=dbinom{n+1}{r+1} ]

    qwq

    [(1+x)^n=sum_{k=0}^ndbinom{n}{k}x^{n-k}=sum_{k=0}^ndbinom{n}{k}x^{k} ]

    (二项式定理)

    组合意义:多项式乘法选数 .

    几道小题

    Problem 1

    (n) 里选 (k) 数,数字可以相同,求方案数.

    一个独特的解法:设选 (a_1le a_2le cdotsle a_k) .
    构造 (g_1=a_1,g_2=a_2+1,g_3=a_3+2,cdots),然后对 (g) 作组合,得答案为

    [dbinom{n+r-1}{r} ]

    Problem 2

    (n) 里选 (k) 数,数字不能相邻,求方案数.

    类似的设选 (a_1< a_2< cdots< a_k) .
    构造 (g_1=a_1,g_2=a_2-1,g_3=a_3-2,cdots),然后对 (g) 作组合,得答案为

    [dbinom{n-r+1}{r} ]

    Problem 3

    计算

    [sum_{k=1}^n dbinom{n}{k}^2 ]

    [egin{aligned}sum_{k=1}^n dbinom{n}{k}^2&=dbinom{n}{k}dbinom{n}{n-k}\&=dbinom{2n}{n}end{aligned} ]

    第二个等号用组合意义:

  • 相关阅读:
    Spring scope注解
    classpath与clsspath*
    Hadoop 5 Hbase 遇到的问题
    Hadoop 3
    Hadoop 4 MapReduce
    Hadoop 2
    Hadoop 1
    毕业设计---jQuery动态生成的a标签的事件绑定
    毕业设计---json,Struts,ajax以及JQuery简单案例
    基于SSH框架的学生选课质量属性分析
  • 原文地址:https://www.cnblogs.com/CDOI-24374/p/14726141.html
Copyright © 2011-2022 走看看