• cyyz : Day 1 数论整理


    声明:感谢修改这篇博客的dsr

    Day 1

    先说一下上午的听课吧,哎~,简直了,简直(⊙o⊙)…咋说呢,引人入胜???No! 是昏昏欲睡好吧。。。一点听课欲都没有(强撑....),一上午停下来简直怀疑人生。下午上机,啥??上机居然断网!!!搞啥子嘛,,,于是整理上午的笔记,╮(╯▽╰)╭内心崩溃。

    一、同余

    知识点:

    同余,如果a和b对m取模得到的结果相同,那么说a和b在模m意义下相等,或者说二者同余,记作a≡b (mod m)(其实中间应该是三条杠,但是打不出来),并且就划分为同一类。显然模m意义下一共有m类数字,以0,1,...,m-1为代表元素。注意负数也是可以取模的,例如-1 mod 3 = 2。如果a=km+r(0<=r<m),那么a=r(mod m),这称作”带余除法”。特殊的,如果r=0,那么m是a的因数,a是m的倍数,称为m整除a,记作m|a。

     

    代码实现:

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<algorithm>
     4 #include<cmath>
     5 using namespace std;
     6 typedef long long ll;
     7 ll a,b,x,y,z;
     8 inline ll read() {
     9     ll n=0,f=1;char ch=getchar();
    10     while (ch<'0' || ch>'9') {if(ch=='-') f=-1;ch=getchar();}
    11     while (ch<='9' && ch>='0') {n=(n<<3)+(n<<1)+ch-'0';ch=getchar();}
    12     return n*f;
    13 }
    14 inline void gcd(ll a,ll b) {
    15     if(!b) {
    16         x=1,y=0;
    17         return ;
    18     }
    19     gcd(b,a%b);
    20     z=x,x=y;
    21     y=z-a/b*y;    
    22 }
    23 int main() {
    24     a=read(),b=read();
    25     gcd(a,b);
    26     printf("%lld\n",(x+b)%b);
    27     return 0;
    28 }
    代码实现

    二、因数

    知识点:

    刚才说了,如果a|b,也就是a整除b,那么b是a的倍数,a是b的因数。显然如果a|b,a|c,那么a|(b±c),a|(bx+cy),即a整除b和c的线性组合最大公因数gcd(a,b),或者简写成(a,b),定义为,最大的d,满足d|a且d|b。显然d|(a,b)等价于,d|a且d|b另一个很显然的是,(a,b)=(a+b,b)=(a-b,b)=(a mod b,b)特别的,如果(a,b)=1,那么称作a和b互质最小公倍数[a,b]同理。二者关系:[a,b]=ab/(a,b),注意只对两个数字恒有效。

    三、欧拉定理

    四、逆元

    Exgcd 求逆元 代码实现:

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cmath>
     4 using namespace std;
     5 typedef long long ll;
     6 ll a,b,x,y,z,n,mod;
     7 inline ll read() {
     8     ll n=0,f=1;char ch=getchar();
     9     while (ch<'0' || ch>'9') {if(ch=='-') f=-1;ch=getchar();}
    10     while (ch<='9' && ch>='0') {n=(n<<3)+(n<<1)+ch-'0';ch=getchar();}
    11     return n*f;
    12 }
    13 inline void exgcd(ll a,ll b,ll &x,ll &y) {
    14     if(!b) {
    15         x=1,y=0;
    16         return ;
    17     }
    18     exgcd(b,a%b,x,y);
    19     z=x,x=y;
    20     y=z-a/b*y;    
    21 }
    22 int main() {
    23     n=read(),mod=read();
    24     exgcd(n,mod,x,y);
    25     x=(x%mod+mod)%mod;
    26     printf("%lld\n",x);
    27     return 0;
    28 }
    代码实现

    线性求逆元 代码实现:

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<algorithm>
     4 #include<cmath>
     5 using namespace std;
     6 typedef long long ll;
     7 const int N=3e6+10;
     8 inline int read() {
     9     int n=0,f=1;char ch=getchar();
    10     while (ch<'0' || ch>'9') {if(ch=='-') f=-1;ch=getchar();}
    11     while (ch<='9' && ch>='0') {n=(n<<3)+(n<<1)+ch-'0';ch=getchar();}
    12     return n*f;
    13 }
    14 int n,p,a[N];
    15 int main(){
    16     n=read(),p=read();
    17        a[0]=a[1]=1;
    18     for(int i=2;i<=n;++i) a[i]=a[i]-(ll)(p/i)*a[p%i]%p;
    19     for(int i=1;i<=n;++i) {
    20         if(a[i]<0) a[i]+=p;
    21         printf("%d\n",a[i]);   
    22     }
    23     return 0;
    24 }
    代码实现

     

    五、扩展欧拉定理

     

     

    六、卢卡斯定理

     

     

    代码实现

     1 #include<iostream>
     2 #include<cstring>
     3 #include<cstdio>
     4 #include<cmath>
     5 #include<algorithm>
     6 using namespace std;
     7 typedef long long ll;
     8 const int N=1e5+10;
     9 int n,m,p,k;
    10 ll a[N],b[N];
    11 inline int read() {
    12     int n=0,f=1;char ch=getchar();
    13     while (ch<'0' || ch>'9') {if(ch=='-') f=-1;ch=getchar();}
    14     while (ch<='9' && ch>='0') {n=(n<<3)+(n<<1)+ch-'0';ch=getchar();}
    15     return n*f;
    16 }
    17 inline ll lucas(int x,int y) {
    18     if(x<y) return 0;
    19     else if(x<p) return b[x]*a[y]*a[x-y]%p;
    20     else return lucas(x/p,y/p)*lucas(x%p,y%p)%p;
    21 }
    22 int main() {
    23     k=read();
    24     while (k--) {
    25         n=read(),m=read(),p=read();
    26         a[0]=a[1]=b[0]=b[1]=1;
    27         for(int i=2;i<=n+m;++i) b[i]=b[i-1]*i%p;
    28         for(int i=2;i<=n+m;++i) a[i]=(p-p/i)*a[p%i]%p;
    29         for(int i=2;i<=n+m;++i) a[i]=a[i-1]*a[i]%p;
    30         printf("%lld\n",lucas(n+m,m)); 
    31     }
    32     return 0;
    33 } 
    代码实现

     

    七、GCD/EXGCD

    代码实现:

    1 inline void exgcd(ll a,ll b,ll &x,ll &y) {
    2     if(!b) {
    3         x=1,y=0;
    4         return ;
    5     }
    6     exgcd(b,a%b,x,y);
    7     z=x,x=y;
    8     y=z-a/b*y;    
    9 }
    主要代码

    青蛙的约会:

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<algorithm>
     4 #include<cstring>
     5 using namespace std;
     6 typedef long long ll;
     7 const int N=100000010;
     8 ll x,y,m,n,l,a,b,js,mod;
     9 
    10 inline ll read() {
    11     ll n=0,f=1;char ch=getchar();
    12     while (ch<'0'||ch>'9') {if(ch=='-') f=-1;ch=getchar();}
    13     while (ch>='0'&&ch<='9') {n=n*10+ch-'0';ch=getchar();}
    14     return n*f;
    15 }
    16 
    17 inline ll gcd(ll a,ll b) {
    18     if(b) return gcd(b,a%b);
    19     else return a;
    20 }
    21 
    22 inline void IU(ll a,ll b,ll &x,ll &y) {
    23     if(!b) { 
    24         x=1,y=0;
    25         return ;
    26     }
    27     IU(b,a%b,y,x);
    28     y-=a/b*x;
    29 }
    30 
    31 inline void pd() {
    32     if((b-a)%js) printf("Impossible\n");
    33     else {
    34         x=(x*((b-a)/js)%mod+mod)%mod;    
    35         printf("%lld\n",x);    
    36     }
    37 }
    38 
    39 int main() {
    40     a=read(),b=read(),m=read(),n=read(),l=read();
    41     js=gcd(m-n,l);
    42     mod=abs(l/js);
    43     IU(m-n,l,x,y);
    44     pd();
    45     return 0;
    46 }
    代码实现

    八、关于二元一次不定方程

    知识点(Zz..摘自度娘):

    使二元一次方程两边相等的一组未知数的值,叫做二元一次方程的一个解.

    对二元一次方程的解的理解应注意以下几点:

    ①一般地,一个二元一次方程的解有无数个,且每一个解都是指一对数值,而不是指单独的一个未知数的值;

    ②二元一次方程的一个解是指使方程左右两边相等的一对未知数的值;反过来,如果一组数值能使二元一次方程左右两边相等,那么这一组数值就是方程的解;

    ③在求二元一次方程的解时,通常的做法是用一个未知数把另一个未知数表示出来,然后给定这个未知数一个值,相应地得到另一个未知数的值,这样可求得二元一次方程的一个解.

    折叠注意点:

    (1)二元一次方程组:由两个二元一次方程所组成的一组方程,叫做二元一次方程组.

    (2)二元一次方程组的解:二元一次方程组中两个方程的公共解,叫做二元一次方程组的解.

    对二元一次方程组的理解应注意:

    ①方程组各方程中,相同的字母必须代表同一数量,否则不能将两个方程合在一起.

    ②怎样检验一组数值是不是某个二元一次方程组的解,常用的方法如下:将这组数值分别代入方程组中的每个方程,只有当这组数值满足其中的所有方程时,才能说这组数值是此方程组的解,否则,如果这组数值不满足其中任一个方程,那么它就不是此方程组的解.

     

    九、CRT

    知识点:

    定理1:几个数相加,如果存在一个加数,不能被整数a整除,那么它们的和,就不能被整数a整除。

    定理2:两数不能整除,若除数扩大(或缩小)了几倍,而被除数不变,则其商和余数也同时扩大(或缩小)相同的倍数(余数必小于除数)。

     

    代码实现:

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<algorithm>
     4 #include<cmath>
     5 using namespace std;
     6 typedef long long ll;
     7 ll m[15],a[15];
     8 int n;
     9 inline ll read() {
    10     ll n=0,f=1;char ch=getchar();
    11     while (ch<'0' || ch>'9') {if(ch=='-') f=-1;ch=getchar();}
    12     while (ch<='9' && ch>='0') {n=(n<<3)+(n<<1)+ch-'0';ch=getchar();}
    13     return n*f;
    14 }
    15 inline int fread() {
    16     int n=0,f=1;char ch=getchar();
    17     while (ch<'0' || ch>'9') {if(ch=='-') f=-1;ch=getchar();}
    18     while (ch<='9' && ch>='0') {n=(n<<3)+(n<<1)+ch-'0';ch=getchar();}
    19     return n*f;
    20 }
    21 inline void gcd(ll a,ll b,ll &d,ll &x,ll &y) {
    22     if(!b){
    23         d=a;
    24         x=1,y=0;
    25     } else{
    26         gcd(b,a%b,d,y,x);
    27         y-=(a/b)*x;
    28     }
    29 }
    30 inline ll work_(int n,ll *m,ll *a) {
    31     ll p=1,d,y,x=0;
    32     for(int i=0;i<n;++i) p*=m[i];
    33     for(int i=0;i<n;++i){
    34         ll w=p/m[i];
    35         gcd(m[i],w,d,d,y);
    36         x=(x+y*w*a[i])%p;
    37     }
    38     return (x+p)%p;
    39 }
    40 int main() {
    41     n=fread();
    42     for(int i=0;i<n;++i) m[i]=read(),a[i]=read();
    43     printf("%lld",work_(n,m,a));
    44 }
    代码实现

     

    十、扩展欧几里得

     

     

    十一、线性筛

    知识点:

    可以在O(n)时间内筛出1~n的所有质数。如果F(n)是个积性函数,根据定义我们只要能够低于O(lgn)的知道每个F(p^c)的值,我们就能在O(n)时间内求出F(1)~F(n)。具体做法是这样的,每次枚举一个数字i,枚举所有已经筛出来的1~i中的质数k,那么x=ik不是质数,并且k是x的最小质因子。如果i%k==0,就break掉k的循环。可以证明每个数字都只会被其最小的质因子筛去,同时利用这个性质可以顺便筛出一些积性函数。这样你可以维护每个数字的最小质因子lp[n],最小质因子对应的那个若干次方lpc[n],这样对于积性函数每次只要计算满足lpc[n]=n的那些F[n],然后用积性函数的性质就可以维护1~n的F。

    代码实现:

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 using namespace std;
     5 const int N=10000010;
     6 int n,m,x;
     7 bool vis[N]={1,1};
     8 int a[N];
     9 inline int read() {
    10     int n=0,f=1;char ch=getchar();
    11     while (ch<'0' || ch>'9') {if(ch=='-') f=-1;ch=getchar();}
    12     while (ch<='9' && ch>='0') {n=(n<<3)+(n<<1)+ch-'0';ch=getchar();}
    13     return n*f;
    14 }
    15 // 1
    16 inline void ss(int n,int m) {
    17     for(int i=2;i*i<=n;++i) 
    18         if(!vis[i]) 
    19             for(int j=i*i;j<=n;j+=i) vis[j]=true;
    20     while(m--) {
    21         x=read();
    22         if(vis[x]) printf("No\n");
    23         else printf("Yes\n");
    24     }
    25     return;
    26 }
    27 // 2 
    28 inline void IU(int n,int m) {
    29     int js=0;
    30     for(int i=2;i<=n;++i) {
    31         if(!vis[i]) a[++js]=i;
    32         for(int j=1;j<=js&&i*a[j]<=n;++j) {
    33             vis[i*a[j]]=true;
    34             if(i%a[j]==0) break;
    35         } 
    36     }
    37     while(m--) {
    38         x=read();
    39         if(vis[x]) printf("No\n");
    40         else printf("Yes\n");
    41     }
    42 } 
    43 int main() {
    44     n=read(),m=read();
    45     //ss(n,m);
    46     IU(n,m);    
    47     return 0;
    48 } 
    代码实现

     

    十二、BSGS

    知识点:

    bsgs算法,又称大小步算法(某大神称拔山盖世算法)或北上广深算法。

    主要用来解决   A^x=B(mod C)(C是质数),都是整数,已知ABCx

    代码实现(poj 2417):

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cmath>
     4 #include<algorithm>
     5 #include<map>
     6 using namespace std;
     7 typedef long long ll;
     8 map<ll,int> q;
     9 ll p,m,n,a,b,z,ans,t,bz;
    10 inline ll fpow(ll x) {
    11     ll s=1,res=a;
    12     while (x>0) {
    13         if(x&1) s=(s*res)%p;
    14         x=x>>1;
    15         res=(res*res)%p;
    16      }
    17      return s;
    18 }
    19 int main() {
    20     while (scanf("%lld%lld%lld",&p,&a,&b)!=EOF) {
    21         if(a%p==0) {
    22             printf("no solution\n");
    23             continue;
    24         }
    25         q.clear();
    26         m=ceil(sqrt(p));
    27         bz=0,z=b%p,q[z]=0;
    28         for(int i=1;i<=m;++i) z=(z*a)%p,q[z]=i;
    29         t=fpow(m);
    30         z=1;
    31         for(int i=1;i<=m;++i) {
    32             z=(z*t)%p;
    33             if(q[z]) {
    34                 bz=1;
    35                 ans=i*m-q[z];
    36                 printf("%lld\n",(ans%p+p)%p);
    37                 break;
    38             }
    39         }
    40         if(!bz) printf("no solution\n");    
    41     }
    42     return 0;
    43 }
    代码实现

    十三、莫比乌斯反演

    知识点:(摘自度娘~~

    数论函数,就是正整数映射到非负整数的函数。积性函数,如果一个数论函数f满足对于任意(x,y)=1,有f(xy)=f(x)f(y),那么称f是积性函数。显只要知道了所有的f(p^c)就可以知道所有的f(n)完全积性函数,如果一个数论函数满足对于任意xy,都有f(xy)=f(x)f(y),那么称f是完全积性函数

    性质:

      性质一(莫比乌斯反演公式): 

      性质二:μ(n)积性函数

      性质三:设f是算术函数,它的和函数 

           是积性函数,那么 也是积性函数。

     

     莫比乌斯反演定理:

    设f(n) 和g(n) 是定义在正整数集合上的两个函数,定义如下。

           

          

      

    证明:(摘自度娘~

    充分性证明:

             

            

            

             

    考虑到:

           

    因此

            

    必要性证明:

            

     

    考虑到:

               

    因此
            

    证明2

     

     

    例题:

    问题描述

    给定5个整数:a, b, c, d, k,你要在a中找到x。在c b,y…即GCD(x, y) = k, GCD(x, y)表示xy的最大公约数,由于选项的数量可能很大,所以只需要输出不同的数对的总数。请注意,(x=5, y=7)(x=7, y=5)被认为是相同的。

    输入

    输入由几个测试用例组成。输入的第一行是案例的数量。不超过3000例。

    每一种情况包含五个整数:abcdk0 < a <= b <= 100,000, 0 < c <= d <= 100,000, 0 <= k <= 100,000,如上所述。

    输出

    对于每个测试用例,打印选项的数量。使用示例中的格式。

    样例输入

    2

    1 3 1 5 1

    1 11014 1 14409 9

    样例输出

    案例1:9

    案例2:736427

    代码实现:

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cmath>
     4 #include<algorithm>
     5 #include<map>
     6 using namespace std;
     7 typedef long long ll;
     8 const int N=1e5+10;
     9 int v[N],a[N],b[N];
    10 int n,m,js,jc,x,y,z,k;
    11 ll res,ans;
    12 inline int read() {
    13     int n=0,f=1;char ch=getchar();
    14     while (ch<'0' || ch>'9') {if(ch=='-') f=-1;ch=getchar();}
    15     while (ch<='9' && ch>='0') {n=(n<<3)+(n<<1)+ch-'0';ch=getchar();}
    16     return n*f;
    17 }
    18 int main() {
    19     b[1]=1;
    20     for(int i=2;i<=100000;++i) {
    21         if(!v[i]) a[++js]=i,b[i]=-1;
    22         for(int j=1;j<=js;++j) {
    23             int k=a[j]*i;
    24             if(k>100000) break;
    25             v[k]=1;
    26             if(i%a[j]==0) { 
    27                 b[k]=0;
    28                 break;
    29             } else b[k]=-b[i]; 
    30         }
    31     }
    32     k=read();
    33     while(k--) {
    34         ++jc;
    35         res=ans=0;
    36         n=read(),m=read(),x=read(),y=read(),z=read();
    37         if(!z) { 
    38             printf("Case %d: 0\n",jc);
    39             continue;
    40         }
    41         m/=z;y/=z;
    42         if(m>y) swap(m,y);
    43         for(int i=1;i<=m;++i) res+=(ll)b[i]*(m/i)*(y/i);
    44         for(int i=1;i<=m;++i) ans+=(ll)b[i]*(m/i)*(m/i);
    45         printf("Case %d: %lld\n",jc,res-ans/2);
    46     }
    47     return 0;
    48 }
    代码实现

    十四、狄利克雷卷积

    十五、数论分块

  • 相关阅读:
    【百度之星2014~初赛(第二轮)解题报告】Chess
    Cocos2d-x3.0游戏实例之《别救我》第二篇——创建物理世界
    【CSS】使用CSS控制文字过多自动省略号
    【jar】JDK将单个的java文件打包为jar包,并引用到项目中使用【MD5加密】
    【JSP EL】el表达式判断是否为null
    【redis】5.spring boot项目中,直接在spring data jpa的Repository层使用redis +redis注解@Cacheable直接在Repository层使用,报错问题处理Null key returned for cache operation
    【Exception】查看异常出现在具体的文件名/类名/方法名/具体行号
    【bootstrap】使用支持bootstrap的时间插件daterangepicker
    【css】设置div位于浏览器的最底层,离用户最远
    【前台】【单页跳转】整个项目实现单页面跳转,抛弃iframe
  • 原文地址:https://www.cnblogs.com/Darkpurple/p/9415866.html
Copyright © 2020-2023  润新知