ACM中数论基础知识的运用.docx
- 文档编号:25695625
- 上传时间:2023-06-11
- 格式:DOCX
- 页数:26
- 大小:27.14KB
ACM中数论基础知识的运用.docx
《ACM中数论基础知识的运用.docx》由会员分享,可在线阅读,更多相关《ACM中数论基础知识的运用.docx(26页珍藏版)》请在冰豆网上搜索。
ACM中数论基础知识的运用
数论初步:
一,整除与因式分解:
1,算术基本定理:
n=a1^r1*a2^r2*a3^r3……
2,求素数:
(试除法,筛选法):
素数测试
费马小定理:
若p为素数,则对于任意小于
p的正整数a,有a(p-1)≡1(modp)
证明:
用欧拉定理直接得出
二次探测定理:
若p为素数,a2≡1(modp)
小于p的正整数解只有1和p-1
满足费马小定理和二次探测定理的数可以确定是素数
Miller-Rabin算法
算法步骤:
判定n是否为素数
令n-1=m*2j,m为奇数
随机在2到(n-1)之间取一个整数b
令v=bm,之后每次对v平方,当v=1时,若上一次的v既
不是1也不是(n-1),由二次探测定理,n不是素数,退出;
不断循环直到计算出b(n-1)
v=1,满足费马小定理,通过测试;否则n一定不是素数
选取几个不同的b多次测试
Miller-Rabin只能算一种测试,因为通过
测试的数不一定是素数,非素数通过测试
的概率是1/4
虽然一次测试的结果不一定令人满意,但
五六次随机测试基本可以保证正确率超
过99.9%
For(inti=2;i { For(intj=2,flay=1;j If(I%j==0) { Printf(“i不是素数”); flay=0; } Printf(“I是素数”); } 3, intm=sqrt(n+0.5); intc=0; memset(vis,0,sizeof(vis)); for(inti=2;i<=m;i++) if(! vis[i]) { prime[c++]=i; for(intj=i*i;j<=n;j+=i)vis[j]=1; } 4, intisprime[N]; intcnt; intisok(intx) { for(inti=0;i if(x%isprime[i]==0)return0; return1; } voidgetprime() { isprime[0]=2; isprime[1]=3; cnt=2; for(inti=5;i if(isok(i)) isprime[cnt++]=i; } 5,因式分解: intFactor(intnum) { intm=0; for(inti=0;i { if(num%isprime[i]==0) { arr[++m]=isprime[i]; r[m]=0; while(num%isprime[i]==0&&num) { r[m]++; num/=isprime[i]; } } } if(num>1) { arr[++m]=num; r[m]=1; } returnm; } 6,求约数: voiddfs(intnow,intq,intm,inta,intb) { if(flay)return; if(q>a)return; if(now==m+1) { q就是约数….. return; } for(inti=0,t=1;i<=r[now];i++,t*=arr[now]) { dfs(now+1,q*t,m,a,b); } } 例题分析: Fzu上的题: () 求一个数的真因子个数(不包括本身)。 n=p1^a1*p2^a2...pn^an. 那么真因子的个数就为: (a1+1)*(a2+1)...(an+1)-1; 求n的所有真因子的和。 由n=p1^a1*p2^a2...pr^ar. 再由生成函数得(1+p1+p1^2...+p1^a1)*(1+p2+p2^2...+p2^a2)...(1+pr+pr^2...pr^ar). 求最小公倍数为M的至少两个数的最小和。 m=p1^a1*p2^a2...pn^an. 当m=1时: sum=2 当m为素数时或m=p^n时: sum=m+1 当m=2147483647: sum=m+1. sum=(p1^a1)+p2^a2...+pn^an. 1,(四省赛)题意: 求x,y,满足x+y=a,lcm(x,y)=b,x,y. 思路: 因为,a<20000,b<=10^9.一开始想法是从1到a/2枚举x,然后再判断lcm是否为b.可是数据组数有10^5这样会TEL。 然后再想想发现,因为lcm(x,y)=b,所以x必定为b的因子,于由只要枚举b的因子就行了。 常识: 1到10^6内平均的约数个数仅为13.97个。 voiddfs(intnow,intq,intm,inta,intb) { if(flay)return; if(q>a)return; if(now==m+1) { intx=q; inty=a-x; if(lcm(x,y)==b) { flay=true; if(x>y)swap(x,y); printf("%d%d\n",x,y); } return; } for(inti=0,t=1;i<=r[now];i++,t*=arr[now]) { dfs(now+1,q*t,m,a,b); } } 变形题1: 求x,y,满足x+y=a,gcd(x,y)=b,x,y; 这可以看出b为x,y,的因子,要构造x,y,只要枚举b*k(k在1...)。 变形题2: 已知最大公约数gcd(x,y)=a,lcm(x,y)=b,求有多少个满足条件的? voiddfs(intnow,intq,intm) { if(now==m+1) { //if(q%x==0)/*注释的方法会超时*/ //arr[p++]=q;/*设p=a*x,q=b*x,则由gcd(p,q)=x,得gcd(a,b)=1 得y=a*b*x,x*y=a*b*x*x,dfs枚举到的一个q后,q定等于b*x, 于是将x*y/q之得到的p,判断gcd(p,q)? =x*/ intt=x*y/q;//x=gcd(p,q),y=lcm(p,q);p*q=gcd(p,q)*lcm(p,q);p=x*y/q; if(gcd(t,q)==x) c++; return; } for(inti=0,t=1;i<=r[now];i++,t*=a[now]) dfs(now+1,q*t,m); } 2,求最大的i使得n! %k^i==0;(想想: N! 如何分解….) LLgetsum(LLn,LLx) { LLret=0; while(n) { ret+=n/x; n/=x; } returnret; } LLsolve(LLn,LLk) { LLans=(LL)inf,tmp; LLxsum; for(inti=0;i { if(k%isprime[i]==0) { xsum=0; while(k%isprime[i]==0) { k/=isprime[i]; xsum++; } tmp=getsum(n,isprime[i]); tmp/=xsum; ans=min(ans,tmp); } } if(k>1) { tmp=getsum(n,k); ans=min(ans,tmp); } returnans; } 二,殴拉函数: 定义: 对于正数n,殴拉函数是小于等于n的数中与n互质的数的个数: f(n); 如果n是素数: f(n)=n–1;f(n^k)=n^k–n^k-1; 容易证明φ(n)=p^k-p^(k-1) 证明: 已知少于小于p^k的正整数个数为p^k-1个,其中 和p^k不互质的正整数有{p×1,p×2,...,p×(p^(k-1)-1)}共计p^(k-1)-1个 所以φ(n)=p^k-1-(p^(k-1)-1)=p^k-p^(k-1) 如果: gcd(n,m)==1那么: f(n*m)=f(n)*f(m); Euler定理若gcd(a,n)=1则aϕ(n)≡1(modn) •意义: 当b很大时ab≡abmodϕ(n)(modn),让 指数一直比较小 所以当: n=p1^a1*p2^a2…. F(n)=(p1^a1–p1^a1-1)*(p2^a2–p2^a2-1)…..=>(p1-1)*(p2-1)*…..(p1^(a1-1)*p2^(a2-1)….); F(n)=n*(1-1/p1)*(1-1/p2)….. intelua(intn) { intret=1; for(inti=2;i*i<=n;i++) { if(n%i==0) { n/=i; ret*=i-1; while(n%i==0) { n/=i; ret*=i; } } } if(n>1)ret*=n-1; returnret; } 例题分析 1: pku2478,求出分数a/b,其中数1<=a 思路: (就是求小于n的把有整数a,并且sum(gcd(a,n)=1(1<=a ) 2,hdu2588: 有多少个正整数X满足: 1<=X<=N,并且gcd(X,N)>=M. 算法: 由: 1<=x<=N且(x,N)>=M;得(N/M,x/M)>=1推出: (N/q,x')==1当{1<=x'<=N/q且q>=M};所以推出结果就是统计: sum(euler(N/q)){当q|N,且q>=M}所以: 只要对N进行因子分解,求出它的约数,再统计约数q大于M的euler(N/q); 3,hdu3501(2010HIT多校)求小于N的不与N互质的数的和 思路: 容斥原理,求反面。 设: 小于N与N互质的数为: a[1],a[2]…..a[phi(N)]; 对于1<=i<=phi(N),因为: gcd(N,a[i])=1可得gcd(N,N-a[i])=1; (反证法,设gcd(N,N-a[i])=k>1,=>k|N且k|(N-a[i]),=>k|a[i]k|gcd(N,a[i])这与gcd(N,a[i])=1矛盾), 所以得s=a[1]+a[2]…+a[phi(N)] S=N-a[1]+N-a[2]….+N–a[phi(N)]=>s=N*phi(N)/2; 变形题: 求小于N的所有数与N的最大公约数之和。 思路: 设K=gcd(i,n)(1<=i<=n)那么最大公约数为K的个数是phi(n/K),和就是K*phi(n/K). 4,去年的大连赛区现场题: zju3547.. #include #include #include #include #include #defineLLlonglong #definemod1000000007 #definemaxn10000 usingnamespacestd; intpi[1000],m; intisprime[1300],cnt; intisok(intx) { for(inti=0;i if(x%isprime[i]==0)return0; return1; } voidgetprime() { cnt=2; isprime[0]=2; isprime[1]=3; for(inti=5;i if(isok(i))isprime[cnt++]=i; } LLMypro(LLa,LLb,LLc) { LLret=0; while(b>0) { if(b&1) if((ret+=a)>c)ret-=c; if((a+=a)>c)a-=c; b>>=1; } returnret; } LLMypow(LLa,intb,LLc) { LLret=1; while(b>0) { if(b&1) ret=Mypro(ret,a,c); a=Mypro(a,a,c); b>>=1; } returnret; } LLn_30; LLsum(intn) { LLret; ret=Mypow(n,5,mod)*6%mod; ret=(ret+15*Mypow(n,4,mod)%mod)%mod; ret=(ret+10*Mypow(n,3,mod)%mod)%mod; ret=(ret-n)%mod; ret=(ret+mod)%mod; ret=Mypro(n_30,ret,mod); returnret; } LLdfs(intx,intn) { LLret=0; LLtemp; for(inti=x;i { temp=pi[i]; ret=(ret+(sum(n/temp)*(temp*temp%mod*temp%mod*temp%mod))%mod)%mod; ret=((ret-(dfs(i+1,n/temp)*(temp*temp%mod*temp%mod*temp%mod)%mod))%mod+mod)%mod; } returnret%mod; } intmain() { getprime(); intcs; intn; scanf("%d",&cs); n_30=Mypow(30,mod-2,mod); while(cs--) { scanf("%d",&n); if(isok(n)) { printf("%lld\n",sum(n-1)); continue; } LLN=n; m=0; for(inti=0;i { if(n%isprime[i]==0) { pi[m++]=isprime[i]; n/=isprime[i]; while(n%isprime[i]==0) n/=isprime[i]; } } if(n>1)pi[m++]=n; n=N; printf("%lld\n",((sum(n)-dfs(0,n))%mod+mod)%mod); } return0; } for (int ind = 1; ind < (1 << cnt); ++ind) { int token = ind; LL tmp = 1; int t = 0; for (int j = 0; j < cnt; ++j, token >>= 1) { if (token & 0x1) { tmp *= vt[j]; ++t; } } if (t & 0x1) { res = ( res + ( MOD - ( pow_mod(tmp, 4) * fun(n / tmp) % MOD ) ) ) % MOD; } else { res = ( res + pow_mod(tmp, 4) * fun(n / tmp) ) % MOD; } } Euler定理若gcd(a,n)=1则a^ϕ(n)≡1(modn) •意义: 当b很大时a^b≡a^bmodϕ(n)(modn),让 指数一直比较小 A^xmodc=(A^(xmodphi(c)+phi(c)))modc; 费马小定理: 设p是素数,a是任意整数且a! =0(modp),则有: a^p-1=1(modp). 三,线性方程扩展殴几里德。 整除的性质 性质1: a|b,b|c=>a|c 性质2: a|b=>a|bc 性质3: a|b,a|c<=>a|xb±yc 性质4: a|b,b|a<=>a=±b 性质5: a=kb±c<=>a,b的公因数与b,c的 公因数完全相同(利用性质3) 证明: 性质1: 由a|b,b|c得: b=a*q1,c=b*q1=>c=a*q1*q2,命题得证。 性质2: 由a|b得: b=a*q,两边同乘以c,就得b*c=a*q*c,命题得证。 性质3: 必要性: 由a|b,a|c,得: b=a*q1,c=a*q2,推出bx±cy=a(q1*x±q2*y).取x=1,y=0及x=0,y=1,就推出充分性了,命题得证。 性质4: 必要性: 由a|b,b|a得b=a*q1,a=b*q2,推出a=a*q1*q2,因为a≠0所以q1*q2=1,q1=±1,充分性显而易见,命题得证。 性质5: 由性质3可得: a是b与c的公约数,同时,a又是b的约数,所以,a与b的公约数为a等于b与c的公约数 欧几里德算法(辗转相除法,短除法) 原理: 若a≡r(modb),则gcd(a,b)=gcd(b,r)(利 用性质5证明) a=q1*b+r1 b=q2*r1+r2 r1=q3*r2+r3 …. rn-1=qn-1*rn-2+rn-1 rn-2=qn*rn-1+rn rn-1=qn+1*rn+0; 二元一次不定方程形中: a*x+b*y=c. 求a*x+b*y=gcd(x,y),的一组解: (x0,y0); voidex_gcd(LLa,LLb,LL&d,LL&x,LL&y) { if(b==0) { d=a; x=1,y=0; } else { ex_gcd(b,a%b,d,y,x); y=y-x*(a/b); } } 那如果要求: a*x+b*y=c的一组解(x1,y1). 由整除的性3可知: 当c%gcd(a,b)==0时,方程才有解。 。 。 (x0*c/g,y0*c/g);g=gcd(a,b);通解: (x1+k*b/g,y1-k*a/g); X1*a+y1*b=c=x2*a+y2*b;=>(x1-x2)*a=(y2-y1)*b (x1-x2)*a1=(y2-y1)*b1其中: a1=a/g,b1=b/g; 可得gcd(a1,b1)=1,那么(x1-x2)=b1*k,(y2-y1)=a1*k; 例题分析: Joj去年的省赛题: 求最少的步数操作: 使得给定的Y,变成0,Y有四种操作: Y+a,Y-a,Y+b,Y-b….; 算法过程: 设进行了x次的a+操作,进行了y次的b+操作,那么就可以得到方程: a*x+b*y=Y;这就转换成了用殴几里德来解这个方程。 得到了它的一个解(x0,y0)。 通解: x=x0+k*b/g,y=y0–k*a/g; POJ2142 题目大意: 现有质量为a和b的砝码,数量不限 要求在天平上称出质量为d的物品,天平左右均可放砝码求一种可行方案,要求: 放置砝码数量尽可能少;数量相同时,总质量尽可能少 算法思路: 问题转化: 求ax+by=d的一组整数解(x,y),要求 |x|+|y|尽可能小,若相等,则a|x|+b|y|尽可能小(x<0,表示砝码和物体放在同一侧) 先求出不定方程的一组特解(x0,y0),令 m=gcd(a,b),a'=a/m,b'=b/m,则通解为 x=x0+b't,y=y0-a't(a',b'>0,t为整数) 要求输出(|x|+|y|)值最小的一组。 即(|x|+|y|)=|x0+b/g*t|+|y0-a/g*t|=f(t),简单分析,可以知道, |x0+b/g*t|永远递增且大于零。 f(t)只有在 |y0-a/g*t|==0的时候才能取得最小值。 又因为t是整数,所以t应该取(y0*g/a)左右的整数值。 有了
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- ACM 数论 基础知识 运用
![提示](https://static.bdocx.com/images/bang_tan.gif)