ACM简单经典算法

(1)素数判定

bool prime(int x)         
{
    for(int i=2;i*i<=maxn;i++)    //降低时间复杂度
      if(x%i==0)
        return false;
    return true; 
}

(2)筛法素数打表

void getprime(int n)      
{
    int k=0,ans[maxn];
    memset(ans,0,sizeof(ans));
    ans[0]=ans[1]=1;
    for(int i=2;i<=n;i++)
    {
        if(!ans[i])             
          for(int j=i*i;j<=n;j+=i)
            ans[j]=1;              //标记变量
    }
    for(int i=2;i<=n;i++)
      if(!ans[i])                //值为0的都是素数
        ans[k++]=i;
    ans[k]='\0';
    for(int i=0;ans[i]!='\0';i++)
      cout<<ans[i]<<" ";
    cout<<endl; 
}

(3)唯一分解定理

void W(int n)         
{
    int k=0,s[maxn];
    for(int i=2;i<=n;i++)
    {
        if(n%i==0)
        {
            while(n%i==0)           //一定能保证i为素数
              n/=i;
            s[k++]=i;
        }
    }
    for(int i=0;i<k;i++)
      cout<<s[k]<<" ";
    cout<<endl;
}

(4)欧拉公式

N(n)=n*(1-1/p1)*(1-1/p2)···(其中p1、p2为能被n整除的素因子)
1

void euler_phi(int n)         
{
    int sum=n;
    for(int i=2;i<=n;i++)
    {
        if(n%i==0)
        {
            sum=sum/i*(i-1);
            while(n%i==0)
              n/=i;
        }
    }
    if(n>1)
      sum=sum/n*(n-1);
    cout<<sum<<endl;
}

(5)GCD

int gcd(int a,int b)         
{
    return b==0?a:gcd(b,a%b);    //不断递归
}

1
2
3
4

(6)扩展GCD

(求出x,y,满足Ax+By=gcd(A,B) )

int extend_gcd(int a,int b,int &x,int &y)         
{
    if(b==0)
    {
        x=1;
        y=0;
        return a;
    }
    int r=extend_gcd(b,a%b,y,x);  
    y-=x*(a/b);
    return r;
}

(7)中国剩余定理

(中国剩余定理 求出方程组x=a(i)(mod m(i))(0<=i)

int CRT(int a[],int m[],int n)           
{
    int M=1;
    for(int i=0;i<n;i++)
      M*=m[i];
    int ret=0;
    for(int i=0;i<n;i++)
    {
        int x,y;
        int tm=M/m[i];
        extend_gcd(tm,m[i],x,y);
        ret=(ret+tm*x*a[i])%M;
    }
    return (ret+M)%M;
}

(8)进制转换

(x进制的数转换成y进制 )

string transform(int x,int y,string s)   
{
    string res="";
    int sum=0;
    for(int i=0;i<s.length();i++)
    {
        if(s[i]=='-')
          continue;
        if(s[i]>='0'&&s[i]<='9')      //十进制以内
          sum=sum*x+s[i]-'0';
        else
          sum=sum*x+s[i]-'A'+10;      //十进制之外
    }
    while(sum)
    {
        char tmp=sum%y;
        sum/=y;
        if(tmp<=9)
          tmp+='0';
        else
          tmp=tmp-10+'A';
        res=tmp+res;
    }
    if(res.length()==0)
      res="0";
    if(s[0]=='-') 
      res='-'+res;
    return res;
}

(9)快速幂取模

(求a的i次幂对n的模 )

void quickpow_mod(int a,int i,int n)         
{
    int k=a%n,sum=1;
    while(i)
    {
        if(i&1)
          sum=sum*k%i;
        k=k*k%a;
        n>>=1;
    }
    cout<<sum<<endl;
}

(10)星期计算

(蔡勒公式 给定一个日期,求出这一天是星期几,返回ans,表示是星期(ans+1) )

int whatday(int day,int mon,int year)   
{
    int ans;
    if(mon==1||mon==2)
    {
        mon+=12;
        year--;
    }
    if((year<1752)||(year==1752&&mon<9)||(year==1752&&mon==9&&day<3))   //当日期在1752年9月3日之前
      ans=(day+2*mon+3*(mon+1)/5+year+year/4+5)%7;
    else  
      ans=(day+2*mon+3*(mon+1)/5+year+year/4-year/100+year/400)%7;
    return ans;
} 

(11)闰年判断

bool Isleap(int year)           
{
    if(year%400==0||year%100&&year%4==0)
      return true;
    return false;
}

1
2
3
4
5
6

(12)日期计算

int leap(int y)           
{
    if(!y)
      return 0;
    return y/4-y/100+y/400;
}

int  calc(int day,int mon,int year)       
{
    int res=(year-1)*day+leap(year-1);
    int s[12]={31,28,31,30,31,30,31,31,30,31,30,31};
    for(int i=1;i<mon;i++)
      res+=s[i];
    if(Isleap(year)&&mon>2)
      res++;
    res+=day;
    return res;
} 

void count_day(int da,int ma,int ya,int db,int mb,int yb)  
{
    int resa=calc(da,ma,ya);
    int resb=calc(db,mb,yb);
    cout<<abs(resa-resb)<<endl; 
}

二、常见递推,特殊计数

(13)Catalan数

( 1,1,2,3,5,14,42,132,429,1430,4862,16796)

f(n)=f(2)*f(n-1)+f(3)*f(n-2)+…+f(n-1)*f(2) 边界是f[2]=f[3]=1;
1

void Catalan(int n)        
{
    long long count=1;
    for(int i=1,j=2*n;i<=n;i++,j--)
      count=count*j/i;
    cout<<count/(n+1)<<endl;
} 

(14)第二类Stirling数、Bell数

(结果b[n]对c取模 )(1,2,5,15,52,203,877,140,147,975,当n=100时,b[n]=751)

#define c 1000
long long a[2005][2005]={1};
long long b[2005];
void Bell(int n,int c)           
{
    for(int i=1;i<=2000;i++)
    {
        a[i][0]=0;
        a[i][i]=1;
        for(int j=1;j<i;j++)
          a[i][j]=(a[i-1][j-1]+j*a[i-1][j])%c;
    }
    for(int i=1;i<=2000;i++)
    {
        b[i]=0;
        for(int j=0;j<=i;j++)
          b[i]=(b[i]+a[i][j])%c;
    } 
    cout<<b[n]<<endl;
}

(15)错排计数

(给出n,求出1~n的错排个数占n个数全排列的百分比

错排公式:Dn=(1-1+1/2!-…+[(-1)^n]*1/n!)*n!)
1

void Cuopai(int n)       
{
    double sum,sign=1.0;
    if(n==1)
      sum=0;
    else
    {
        sum=0;
        long long k=1;
        for(int i=2;i<=n;i++)
        {
            k*=i;
            sum=sum+sign/(k*1.0);
            sign=-sign;
        }
        sum*=100;
    }
    printf(".2%%lf",sum);
}

(16)全排列

(字符串S字母的全排列输出 (可转化应用于数组))

void Pailie(char s[])         
{
    int len=strlen(s);
    sort(s,s+len);
    do
    {
        cout<<s<<endl;
    }while(next_permutation(s,s+len));
}

**

(17)三角形计数

**(从1~n任意选择三个数,并且保证三边长能够组成三角形)(0,1,3,7,13,22,34,50,70,95,125,161,203,252,308,372,444)

f(n)=f(n-1)+((n-1)*(n-2)/2-(n-1)/2)/2 边界是f[3]=0;
1

void TC(int n)
{
    long long a[maxn];
    a[3]=0;
    for(i=4;i<maxn;i++)
      a[i]=a[i-1]+((i-1)*(i-2)/2-(i-1)/2)/2;
    cout<<a[n]<<endl;
}

(18)折线分割平面

(0,5,14,27,44,65,90,119,152,189,230,275,324,377,434)

f(n)=f(n-1)+4*(n-1))+1 边界f[1]=0;
1

void ZX(int n)       
{
    long long a[maxn];
    a[1]=0;
    for(int i=2;i<10005;i++)
      a[i]=a[i-1]+4*(i-1)+1;
    cout<<a[n]<<endl;
} 

(19)三色问题

(3,6,6,18,50,66,126,258,510,1026,2046,4098,8190,16386,32766)

f(n)=f(n-1)+f(n-2)*2 边界f[0]=0;
1

void RPG(int n)        
{
    long long s[55]; 
    s[0]=0;s[1]=3,s[2]=6;s[3]=6;
    for(int i=4;i<=50;i++)
      s[i]=s[i-1]+s[i-2]*2;
    cout<<s[n]<<endl;
}

(20)骨牌铺方格I(两层)

(1,2,3,5,8,13,21,34,55,89,144,233,377,610,987)

f(n)=f(n-1)+f(n-2) 边界f[0]=0;

void GPI(int n)
{
long long s[50];
s[0]=0,s[1]=1,s[2]=2;
for(int i=3;i<50;i++)
s[i]=s[i-1]+s[i-2];
cout<<s[n]<<endl;
}

(21)骨牌铺方格II(三层)

(3,11,41,153,571,2131,7953,29681,110771)

f(n)=3f(n-2)+2(f(n-4)+…+f(2)); (n为偶数,且f(0)=1,f[2]=3)

void GPII(int n)       
{
    int a[17],sum=0;
    a[0]=0,a[1]=1;
    for(int i=2;i<=16;i++)
    {
        sum=sum+a[i-2];
        a[i]=3*a[i-1]+2*sum;
    }
    if(n%2==1)
      cout<<0<<endl;
    else
      cout<<a[n/2+1]<<endl; 
}

(22)切西瓜问题

(2,3,5,8,12,17,23,30,38,47,57,68)

F(n)=(n*n-n+4)/2;

int QXG(int n)    
{
    return (n*n-n+4)/2;
} 

**

(23) 若sum= 1²+2²+…+n²,求sum

**
公式:sum=n(n+1)(2n+1)/6

  • 2
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Mr顺

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值