1.辗转相除法 欧几里得算法
(1)非递归模板
通常不使用,为了方便理解递归模板使用
int gcd (int a,int b)
{
int r=a%b;
while (r)
{
a=b;
b=r;
r=a%b;
}
return b;
}
(2) 递归模板
经常使用
int gcd (int a,int b)
{
return b?gcd(b,a%b):a;
}
其中? :
相当于
if (b!=0)
return gcd(b,a%b);
else return a;
2.辗转相减法 更相减损术
易超时,不常用
3.素因子法
基本性质
(a+b)%m=(a%m+b%m)%m
(ab)%m=(a%mb%m)%m
(1)非递归模板
ll quickmod (ll a,ll b,ll c)
{
int ret=1;
while (b)
{
if (b&1)//奇数最后一位为1,b%2==1也可用,速度差不多
ret=ret*a%c;
a=a*a%c;
b/=2;//向下取整
}
return ret;
}
(2)递归模板
本题几乎完全引用模板
#include
#include
using namespace std;
int gcd (int a,int b)
{
return b?gcd (b,a%b):a;
}
int main()
{
int a,b;
int g,l;
while (cin>>a>>b)
{
g=gcd(a,b);
l=(a*b)/g;
printf("%d %d\n",g,l);
}
return 0;
}
(1)(TLE)
#include
#include
using namespace std;
int gcd (int a,int b)
{
return b?gcd(b,a%b):a;
}
int main()
{
int a,b,c;
int r;
while (cin>>a>>b)
{
int minn=1000000;
for (int i=a*b;i>b;i--)
{
r=gcd(a,i);
if (r==b&&minn>r)
{
minn=i;
}
}
cout<<minn<<endl;
}
return 0;
}
(2)AC
#include
#include
using namespace std;
int gcd (int a,int b)
{
return b?gcd(b,a%b):a;
}
int main()
{
int a,b;
int r;
while (cin>>a>>b)
{
int minn=1000000;
for (int i=b+1;;i++)
{
r=gcd(i,a);
if (r==b)
{
printf("%d\n",i);
break;
}
}
}
return 0;
}
#include
#include
using namespace std;
int gcd (int a,int b)
{
return b?gcd(b,a%b):a;
}
int main()
{
int n;
long long a[12];
while (cin>>n)
{
for (int i=1;i<=n;i++)
cin>>a[i];
for (int i=1;i<n;i++)
{
a[i+1]=gcd(a[i],a[i+1]);
}
printf("%lld\n",a[n]);
}
return 0;
}
#include
#include
using namespace std;
int gcd (int a,int b)
{
return b?gcd(b,a%b):a;
}
int main()
{
int n;
long long a[12];
while (cin>>n)
{
for (int i=1;i<=n;i++)
cin>>a[i];
for (int i=1;i<n;i++)
{
a[i+1]=(a[i+1]*a[i])/gcd(a[i],a[i+1]);
}
printf("%lld\n",a[n]);
}
return 0;
}
套模板
#include
#include
using namespace std;
long long quickmod (long long a,long long b,long long c)
{
int ret=1;
while (b)
{
if (b&1)
ret=ret*a%c;
a=a*a%c;
b=b/2;
}
return ret;
}
int main()
{
long long a,b,c;
long long re;
while (cin>>a>>b>>c)
{
re=quickmod(a,b,c);
printf("%lld\n",re);
}
return 0;
}
暴力会TLE
直接运用数学公式做
#include
#include
using namespace std;
long long gcd(long long a,long long b)
{
return b?gcd(b,a%b):a;
}
int main()
{
ios::sync_with_stdio(false);
int t;
while (cin>>t)
{
for (int r=0; r<t; r++)
{
long long a,b;
long long x,y;
long long re;
cin>>a>>b;
//y=a-x;
/* for (int i=1;;i++)
{
re=i/gcd(i,a-i)*(a-i);
if (b==re)
{
x=i;
y=a-i;
break;
}
}*///用暴力不会AC
printf("%lld\n",a*a-2*b*gcd(a,b));
}
}
return 0;
}
(1)今天第无数次TLE:)
我疯了 :)
#include
#include
using namespace std;
int gcd (int a,int b)
{
return b?gcd(b,a%b):a;
}
int main()
{
int t;
while(cin>>t)
{
ios::sync_with_stdio(false);
while (t--)
{
int x,y;//1<=x<=y<=1e6
//int a,b;
int temp;
int ans=0;
cin>>x>>y;
//y=y/2;
for (int i=1;i<=y/2;i++)
{
for (int j=y;j>=y/2;j--)
{
temp=gcd(i,j);
if (temp==x&&y==i/x*j)
ans++;
}
}
cout<<ans*2<<endl;
}
}
return 0;
}
(2)
1.将a[3],a[4]都算出来就可以发现规律,可分解,并利用快速幂取模法计算。但因a[n]通式多出一个2,所以可用 (ab)%m=(a%mb%m)%m 公式进行分解
2.数据过大拒绝暴力
#include
#include
using namespace std;
long long quickmod (long long a,long long b,long long c)//a=3,b=n,c=modx<先求3^n取模再利用公式 (a*b)%m=(a%m*b%m)%m
{
int ret=1;
while (b)
{
if (b&1)//奇数最后一位为1,b%2==1也可用,速度差不多
ret=ret*a%c;
a=a*a%c;
b/=2;//向下取整
}
return ret;
}//套用快速幂取模模板
int main()
{
long long n;//注意输入的n的大小,第一次因为将其设成int 就wa了一次 :)
int mod=1000000007;
long long ans1,ans2;
//int a[100000];
while (cin>>n)
{
ios::sync_with_stdio(false);
//a[n]=2*3^n;
/*for (int i=1;i<=1000000007;i++)
a[i]=2*a[i-1]+3*a[i-2];//打个p表*///暴力打表太蠢了
ans1=quickmod(3,n,mod);
ans2=(2%mod*ans1)%mod;
cout<<ans2<<endl;
}
return 0;
}
#include
#include
using namespace std;
int main()
{
int n;
int a[1000];
int r=0;
while (cin>>n)
{
int sum=0;
int ans=1;
while (n!=0)
{
a[r]=n%2;
n=n/2;
r++;
}//转化为二进制
for (;r>0;r--)
if(a[r-1]==1)
sum++;
for (int i=0;i<sum;i++)
ans*=2;
cout<<ans<<endl;
}
return 0;
}
#include
using namespace std;
int gcd(int a,int b)
{
return b ?gcd(b,a%b):a;
}
int main()
{
long long x,y,t,k;
long long i,j,sum;
ios::sync_with_stdio(false);//提高输入输出效率
while(cin>>t)
{
sum=0;
while(t--)
{
sum=0;
cin>>x>>y;
for(i=x;i<=y;i++)
{
j=x*y/i;
if(x*y%i==0&&j>=x&&j<=y&&gcd(i,j)==x)//注意此处的限制条件,易丢弃j>=x和j<=y
sum++;
}
cout<<sum<<endl;
}
}
return 0;
}
(1)处我一开始写的是下面的代码,结果开始了TLE之旅。。。。
本题解用暴力,但应只用一层for 循环,否则易TLE。
for (i=1;i<n;i++)
{
if (n%i==0)
ans+=1;
}
#include
using namespace std;
int main()
{
ios::sync_with_stdio(false);//提高输入输出效率
long long x,y;
long long n;
int i;
cin>>x>>y;
int ans=0;
n=__gcd(x,y);//c++中可直接使用 ————gcd(x,y)
for (i=1;i*i<n;i++)
{
if (n%i==0)
ans+=2;//(1)
}
if (i*i==n) ans++;
cout<<ans<<endl;
return 0;
}
终于全做完了,今天可怕的不是WA而是TLE,今天是TLE的一天。