算法学习总结

算法记录:

gcd算法(gcd算法用于求解最大公约数的方法,利用了欧几里得算法,即辗转相除法。)

最重要的等式(核心中的核心):gcd(a,b) = gcd(b,a mod b) (不妨设a>b 且r=a mod b ,r不为0)

普通方法:

int gcd(int m,int n)
{    
    int t,r;    
    if (m<n)//为了确保是大数除小数    
    {        
        t=m;        
        m=n;       
        n=t;    
    }    
 
    while((m%n)!=0)//辗转相除    
    {        
        r=m%n;        
        m=n;        
        n=r;    
    }   
 
    return n;
}

递归方法:(比较推荐)

int gcd(int x, int y)
{   if (y)          
            return gcd(y, x%y);     
        else            
            return x;
相关算法题:

本题的要求很简单,就是求N个数字的和。麻烦的是,这些数字是以有理数分子/分母的形式给出的,你输出的和也必须是有理数的形式。

输入格式:

输入第一行给出一个正整数N(≤100)。随后一行按格式a1/b1 a2/b2 ...给出N个有理数。题目保证所有分子和分母都在长整型范围内。另外,负数的符号一定出现在分子前面。

输出格式:

输出上述数字和的最简形式 —— 即将结果写成整数部分 分数部分,其中分数部分写成分子/分母,要求分子小于分母,且它们没有公因子。如果结果的整数部分为0,则只输出分数部分。

输入样例1:

5
2/5 4/15 1/30 -2/60 8/3

输出样例1:

3 1/3

输入样例2:

2
4/3 2/3

输出样例2:

2

输入样例3:

3
1/3 -1/6 1/8

输出样例3:

7/24
#include<bits/stdc++.h>
using namespace std;
int gcd(int x,int y){
    if(y){
        return gcd(y,x%y);
    }else 
        return x;
}
int main(){
    int n,a,b,x,y,s,f;
    scanf("%d",&n);
    scanf("%d/%d",&a,&b);
    for(int i=1;i<n;i++){
        scanf("%d/%d",&x,&y);
        a=a*y+b*x;
        b=b*y;
        s=gcd(abs(a),abs(b));
        a=a/s;
        b=b/s;
    }
    if(b<0){
        a=-a;
        b=-b;
    }
    f=a/b;
    a=a%b;
    if(f==0&&a){
        printf("%d/%d",a,b);
    }else if(a==0) printf("%d",f);
    else printf("%d %d/%d",f,a,b);
    return 0;
}

快速幂取余算法

对于取模运算:(ab)%c=(a%c)(b%c)%c(每一步都将结果控制在c范围以下,有效的防止了数值溢出)

将大数的幂运算拆解成了相对应的乘法运算,类似于取模运算的优化,利用上面的式子,始终将我们的运算的数据量控制在c的范围以下,这样我们可以克服一般的算法的缺点,我们将计算的数据量压缩了很大一部分,当指数非常大的时候这个优化是更加显著的。例如a^5,如果直接运算,需要5次循环了。但是如果写成a^5=a*((a^2)^2),如果是这样,就仅仅需要3次运算了,一下子省了两次运算。

相关算法题:

L1-!的和(10分)

描述

给定两个正整数 N, M,计算 S = (1! + 2! + ... + N!) %M

输入

输出

输入样例 1

2 3

输出样例 1

0

提示

  • 对于 10% 的数据: 100<N≤10。

  • 对于 50% 的数据: 10^30<N≤10^3。

  • 对于 100% 的数据:10^50<N≤10^5。

  • 对于 100%的数据:0<M≤10^9

#include<bits/stdc++.h>
using namespace std;
int main(){
    long long int n,m,sum=0,s=1;
    cin>>n>>m;
    for(int i=1;i<=n;i++){
            s*=i;
             s=s%m;
            sum+=s%m;       
}
     printf("%d",sum%m);
    
    return 0;
}

大数除法算法题(模拟手工运算)

Tom 解决了3的倍数那道题,然后又陷入了沉思。他想知道如果这个数是 3 的倍数,那么这个数除以 3 的结果是多少呢?请你帮帮他。

输入

第一行一个整数 T(0 < T <=10^3)T(0<T≤10^3)。

接下来 T 行,每行输入一个数 x。

输出

共 T行。

  • 如果 x 是 3 的倍数,就输出x/3 的结果

  • 如果不是,就输出NO!NO!NO!

输入样例 1

2
33
11

输出样例 1

11
NO!NO!NO!

 

#include <bits/stdc++.h>
using namespace std;
const int manx=1e3;
#define ll long long
string s;
vector<ll> v;
​
int main()
{
    ll t;
    cin>>t;
    while(t--)
    {
        ll sum=0;
        cin>>s;
        ll len=s.size();
        for(ll i=0;i<len;i++)
        {
            sum=sum+s[i]-'0';
        }
        if(sum%3)
            cout<<"NO!NO!NO!\n";
        else
        {
            v.clear();
            ll temp=0;
            int flag=0;
            for(ll i=0;i<len;i++)
            {
                temp=(temp*10+(s[i]-'0'));
                
                if(temp/3&&flag==0)
                {
                    flag=1;
                    v.push_back(temp/3);
                }
                else if(flag)
                {
                    v.push_back(temp/3);
                }
                
                temp=temp%3;
            }
            ll len2=v.size();
            for(ll i=0;i<len2;i++)
            {
                cout<<v[i];
            }
            cout<<endl;
        }
    }
    return 0;
 }
​

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值