算法记录:
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;
}