• 数学瞎整理


     

    一.质数

     1.筛质数:有两种 一个线性筛,一个欧拉筛。一般用欧拉筛就行了,如果是求一个[l,r] l r大但差的绝对值小的区间,先用线性筛筛前面,然后用欧拉筛筛后面

      欧拉筛O(N log log N)注意每次i循环从2开始 j从i开始 

     1 bool v[N];
     2 int n;
     3 void prime(int n)
     4 {
     5     memset(v,0,sizeof(v));
     6     for(int i=2;i<=n;i++)
     7     {
     8         if(v[i]) continue;
     9         cout<<i<<" ";
    10         for(int j=1;j<=n/i;j++) v[i*j]=1;
    11     }
    12 }

      线性筛 O(N):j从1开始

     1 void primes(int n)
     2 {
     3     memset(v,0,sizeof(v));
     4     cnt=0;
     5     for(int i=2;i<=n;i++)
     6     {
     7         if(!v[i]) prime[++cnt]=i,v[i]=i;
     8         for(int j=1;j<=cnt;j++)
     9         {
    10             if(prime[j]>v[i]||prime[j]>n/i) break;
    11             v[i*prime[j]]=prime[j];
    12         }
    13     }
    14     for(int i=1;i<=cnt;i++)
    15         cout<<prime[i]<<" ";
    16 }

     2.质因数分解:试除法。 结合欧拉筛,扫描2~ √N的每个数d, 若d整除N,从N中除掉所有因子d,同时累计除去的d的个数。

     1 void divide(int n)
     2 {
     3     cnt=0;
     4     for(int i=2;i*i<=n;i++)
     5     {
     6         if(n%i==0) 
     7         {
     8             prime[++cnt]=i; c[cnt]=0;
     9             while(n%i==0) n/=i,c[cnt]++;
    10         }
    11     }
    12     if(n>1) prime[++cnt]=n,c[cnt]=1;
    13     for(int i=1;i<=cnt;i++)
    14         cout<<prime[i]<<"^"<<c[i]<<endl;
    15 }

     3.example

     1 #include<bits/stdc++.h>
     2 #define ll long long 
     3 #define N 10000010
     4 #define mod 998244353
     5 using namespace std;
     6 ll prime[N],cnt,v[N];
     7 ll L,R,ans,ans2;
     8 void pre()
     9 {
    10     for(int i=2;i<1000000;i++)
    11     {
    12         if(v[i]==0) v[i]=i,prime[++cnt]=i;
    13         for(int j=1;j<=cnt;j++)
    14         {
    15             if(prime[j]>v[i]||prime[j]>1000000/i) break;
    16             v[i*prime[j]]=prime[j];
    17         }
    18     }
    19 }
    20 int main()
    21 {
    22     pre();
    23     scanf("%lld%lld",&L,&R);
    24     memset(v,0,sizeof(v));
    25     for(ll i=1;i<=cnt;i++)
    26     {
    27         ll st=max(1ll,(L-1)/prime[i])*prime[i]+prime[i];
    28         for(ll j=st;j<=R;j+=prime[i])
    29         {
    30             if(v[j-L]) continue;
    31             v[j-L]=1;
    32             ans++;
    33             ans2=(ans2+prime[i])%mod;
    34         }   
    35     }
    36     printf("%lld %lld",ans,ans2);
    37     return 0;
    38 }

     二.约数

    • 求约数(集合)

       1.试除法:略

        有一推论:一个整数N的约数个数上界为2√N

       2.倍数法

        推论:1~N每个数的约数个数的总和约为 N log N

     1 vector<int> f[N];
     2 int n;
     3 void pu(int n)
     4 {
     5     for(int i=1;i<=n;i++)
     6         for(int j=1;j<=n/i;j++)
     7             f[i*j].push_back(i);
     8     for(int i=1;i<=n;i++){
     9         for(int j=0;j<f[i].size();j++)
    10             cout<<f[i][j]<<" ";
    11         cout<<endl;
    12     }
    13 }

        3.example 反素数

        见P134

     1 #include<bits/stdc++.h>
     2 #define N 2000000000
     3 #define ll long long
     4 using namespace std;
     5 ll n;
     6 ll ans;
     7 int num=1;
     8 int a[11]={0,2,3,5,7,11,13,17,19,23,29};
     9 void dfs(int dep,int dex,ll anss,int cnt)
    10 {
    11     if(dep==10)
    12     {
    13         if((anss>ans&&cnt>num)||(anss<=ans&&cnt>=num))
    14         {
    15             ans=anss; 
    16             num=cnt;
    17         }
    18         return;
    19     }
    20     int t=1;
    21     for(int i=0;i<=dex;i++)
    22     {
    23         dfs(dep+1,i,anss*t,cnt*(i+1));
    24         t*=a[dep];
    25         if(anss*t>n) break;
    26     }
    27 }
    28 int main()
    29 {
    30     scanf("%lld",&n);
    31     dfs(1,30,1,1);
    32     printf("%lld
    ",ans);
    33     return 0;
    34 }
    • gcd

       1.定理:

    • gcd(a,b)*lcm(a,b)=a*b

    • gcd(a,b)=gcd(b,a-b)=gcd(a,a-b)  (a>=b)

    • gcd(a,b)=gcd(b,a mod b) (b!=0)

       2.一行gcd:

    1 int gcd(int a,int b)
    2 {
    3     return b?gcd(b,a%b):a;
    4 }

        3.example hankson

        贼毒了...我是用暴力写的....还用了自带函数__gcd()

     1 #include<bits/stdc++.h>
     2 #define N 20000100
     3 #define ll long long
     4 using namespace std;
     5 ll f[N];
     6 int cnt;
     7 ll a0,a1,b0,b1;
     8 int i;
     9 void div(int x)
    10 {
    11     cnt=0;
    12     for(i=1;i*i<=x;i++)
    13         if(x%i==0)
    14         {
    15             f[++cnt]=i;
    16             if(i!=x/i) f[++cnt]=x/i;
    17         }
    18 }
    19 ll ans;
    20 void red(ll &x)
    21 {
    22     ll f=1;x=0;char c=getchar();
    23     while(c<'0'||c>'9'){if(c=='-') f=-1;c=getchar();}
    24     while(c>='0'&&c<='9') {x=x*10+c-'0';c=getchar();}
    25     x*=f;
    26 }
    27 void print(ll x)
    28 {
    29     if(x<0) putchar('-'),x=-x;
    30     if(x>9) print(x/10);
    31     putchar(x%10+'0');
    32 }
    33 int main()
    34 {
    35     ll t;
    36     red(t);
    37     while(t--)
    38     {
    39         red(a0);red(a1);red(b0);red(b1);
    40         div(b1);
    41         ans=0;
    42         for(i=1;i<=cnt;i++)
    43         {
    44             ll yy=__gcd(f[i],b0);
    45             if(b0*f[i]/yy!=b1) continue;
    46             if(__gcd(f[i],a0)==a1) ans++;
    47         }
    48         printf("%lld
    ",ans);
    49     }
    50     return 0;
    51 }

     三.互质和phi

     1.phi(i)指1~i之间与i互质的数个数

     2.

                    

     代码如下:

     1 int phi(int n)
     2 {
     3     int ans=n;
     4     for(int i=2;i*i<=n;i++)
     5         if(n%i==0)
     6         {
     7             ans=ans/i*(i-1);
     8             while(n%i==0) n/=i;
     9         }
    10     if(n>1) ans=ans/n*(n-1);
    11     return ans;
    12 }

     3.性质  (p均为质数)

    • 任意n>1,1~n中与n互质的数的和为 n * phi(n) / 2 ;
    • 若a,b互质,phi(a*b)=phi(a)*phi(b);
    • 若p|n 且 p^2|n, 则phi(n)=phi(n/p)*p;
    • 若p|n 但不满足 p^2|n,则phi(n/p) * (p-1);
    • d|n phi(n)=n;

     

    四.同余

    • PRE

       1.费马小定理:

          

      证明在这里

       2.欧拉定理:若正整数a,n 互质

          

       3. 欧拉定理的推论:

       (mod n)

       由此,我们在计算乘方算式需要取模时,可以先把底数对p取模,指数对phi(p)取模,再计算乘方

    • EXGCD和逆元

       1.exgcd: 用于计算x,y  使得对于任意整数a,b, 存在一对整数x,y,满足ax+by=gcd(a,b)

        

        所以 :

                  

    1 int exgcd(int a,int b,int &x,int &y)
    2 {
    3     if(b==0) { x=1; y=0;return a; }
    4     int d=exgcd(b,a%b,y,x);
    5     y-=a/b*x;
    6     return d;
    7 }
    8 //d=exgcd(a,b,x0,y0);

         调用函数可求得 ax + by = gcd (  x,  y ) 的一组特解,d 为 gcd ( a , b )

  • 相关阅读:
    HiKey软硬件开发环境及其调试
    Android/Linux boot time分析优化
    Suspend to RAM和Suspend to Idle分析,以及在HiKey上性能对比
    使用Minicom基于串口调试HiKey
    系统级性能分析工具perf的介绍与使用
    Workload Automation分析及其使用
    重度使用示波器进行优化分析——一个DSDA项目回顾
    Linux CGroup之freezer分析与应用
    编译自己的Ubuntu内核
    Android中关于cpu/cpuset/schedtune的应用
  • 原文地址:https://www.cnblogs.com/kylara/p/9814360.html
Copyright © 2020-2023  润新知