比赛题目来自各个OJ,经过数据加强
目录
T0: 送分水题
输入格式:
一行,两个整数a, b
输出格式:
一行,一个整数a * b
说明
0 <= a, b <= 2147483648
由于a和b都是<=2147483648的,所以它们乘积可能超长整型哒。。。
然而!用unsigned long long就好了。。。不用写高精度乘法的。
代码:
【过水已隐藏】
T1: 斐波那契和……欧几里得(???)1
输入格式:
一个n,一个m。都是正整数。
输出格式:
gcd(第n个斐波那契数,第m个斐波那契数)
输出这个公约数的后8位就好了(前面的0不要)
说明
1<=n,m<=10^9
这题我给的数据比较水所以这样就能过了:
#include <cstdio>
#include <iostream>
#include <algorithm>
using namespace std;
long long n, m, a[1000001];
int gcd(long long x, long long y)
{
if (!min(x, y))
return max(x, y);
return gcd(min(x, y), max(x, y) % min(x, y));
}
int main()
{
cin >> n >> m;
long long q = gcd(n, m);
a[1] = 1;
a[2] = 1;
for (int i = 3; i <= q; i++)
a[i] = (a[i - 1] + a[i - 2]) % 100000000;
cout << a[q];
return 0;
}
这样就好了。
有这么一个著名式子:gcd(f(n), f(m))=f(gcd(n, m))。证明有一点难,但是这个式子应该听说过的吧?
以下是luogu ID 为浅色调 巨佬的证明:
设n < m, f[n]=a, f[n+1]=b
则f[n+2]=a+b, f[n+3]=a+2b, … f[m]=f[m-n-1]a+f[m-n]b
因为f[n]=a, f[n+1]=b, f[m]=f[m-n-1]a+f[m-n]b
所以f[m]=f[m-n-1]*f[n]+f[m-n]*f[n+1]
又因为gcd(f[n], f[m])=gcd(f[n],f[m-n-1]*f[n]+f[m-n]*f[n+1])
而f[n]|f[m-n-1]*f[n]
所以gcd(f[n],f[m-n]*f[n+1])
再证一个引理:gcd(f[n],f[n+1])=1
证:由欧几里得定理知gcd(f[n],f[n+1])=gcd(f[n],f[n+1]-f[n])=gcd(f[n],f[n-1])=gcd(f[n-2],f[n-1])=……=gcd(f[1],f[2])=1
得证。
由引理和gcd(f[n],f[m])=gcd(f[n],f[m-n]*f[n+1])
所以gcd(f[n],f[m])=gcd(f[n],f[m-n])
即gcd(f[n],f[m])=gcd(f[n],f[m%n])
继续递归,将m1=m%n, 则gcd(f[n],f[m])=gcd(f[n%m1],f[m1])
…
不难发现整个递归都在求解gcd(n, m)
最后递归到出现f[0]时,此时的f[n]就是所求gcd。
q.e.d.
之前说了出的数据比较水不会TLE。。。但之前的代码不是标算。
以下巨佬 浅色调 标准答案:(矩阵加速好可怕)
#include <bits/stdc++.h>
#define il inline
#define ll long long
#define mem(p) memset(&p,0,sizeof(p))
using namespace std;
const ll mod=1e8;
ll n,m;
struct mat{ll a[3][3],r,c;};
il mat mul(mat x,mat y)
{
mat p;
mem(p);
for(int i=0;i<x.r;i++)
for(int j=0;j<y.c;j++)
for(int k=0;k<x.c;k++)
p.a[i][j]=(p.a[i][j]+x.a[i][k]*y.a[k][j])%mod;
p.r=x.r,p.c=y.c;
return p;
}
il void fast(ll k)
{
mat p,ans;
mem(p),mem(ans);
p.r=p.c=2;
p.a[0][0]=p.a[0][1]=p.a[1][0]=1;
ans.r=1,ans.c=2;
ans.a[0][0]=ans.a[0][1]=1;
while(k)
{
if(k&