20190731

T1,T2,T3:见提高组模版

T4superGCD:

.

题目描述

Sheng bill有着惊人的心算能力,甚至能用大脑计算出两个巨大的数的GCD(最大公约 数)!因此他经常和别人比赛计算GCD。有一天Sheng bill很嚣张地找到了你,并要求和你比 赛,但是输给Sheng bill岂不是很丢脸!所以你决定写一个程序来教训他。

输入格式

共两行: 第一行:一个数A。 第二行:一个数B。

输出格式

一行,表示A和B的最大公约数。

输入输出样例

输入 #1复制

12
54

输出 #1复制

6

说明/提示

对于20%的数据,0 < A , B ≤ 10 ^ 18。 对于100%的数据,0 < A , B ≤ 10 ^ 10000。

2018-06-08 xenonex提供一组hack的数据

#include <algorithm>
#include <cstring>
#include <cstdlib>
#include <cstdio>
using namespace std;

const int base = 1e9;
const int N = 1e4 + 10;

struct Int {
    int len, n[N / 9 + 10];
    Int() {}
    Int(char * s) {
        int x = strlen(s);
        len = x / 9 + (x % 9 ? 1 : 0);
        int p = x - 1;
        for(int i = 1; i <= len; i ++) {
            n[i] = 0;
            for(int j = min(p, 8); j >= 0; j --)
                n[i] = n[i] * 10 + (s[p - j] & 15);
            p -= 9;
        }
    }
    bool zero() { return len == 1 && n[1] == 0; }
    bool judge() { return !zero() && 0 == (n[1] & 1); }
    bool operator < (const Int &b) const {
        if(len != b.len) return len < b.len;
        for(int i = len; i >= 1; i --)
            if(n[i] != b.n[i]) return n[i] < b.n[i];
        return 0;
    }
    bool operator -= (const Int &b) {
        for(int i = 1; i <= len; i ++) {
            if(i <= b.len) {
                n[i] -= b.n[i];
                if(n[i] < 0) n[i + 1] --, n[i] += base;
            }
        }
        for(; !n[len] && len > 1; len --);
        return zero();
    }
    void div2() {
        for(int i = 1; i <= len; i ++) {
            if(n[i] & 1) n[i - 1] += base >> 1;
            n[i] >>= 1;
        }
        for(; !n[len] && len > 1; len --);
    }
    void operator <<= (const int &x) {
        for(int t = 1; t <= x; t ++) {
            n[len + 1] = 0;
            for(int i = len; i >= 1; i --) {
                n[i] <<= 1; n[i + 1] += n[i] / base; n[i] %= base;
            }
            if(n[len + 1]) len ++;
        }
        this -> print();
    }
    void print() {
        for(int i = len; i >= 1; i --)
            if(i == len) printf("%d", n[i]);
            else printf("%09d", n[i]);
        printf("\n");
    }
} x, y;

int main() {
    static char A[N], B[N];
    scanf("%s %s", A, B);
    x = Int(A), y = Int(B);
    if(x.zero()) return y.print(), 0;
    if(y.zero()) return x.print(), 0;
    int i = 0, j = 0;
    for(; x.judge(); i ++) x.div2();
    for(; y.judge(); j ++) y.div2();
    while(1) {
        if(!(x < y)) {
            if(x -= y) return y <<= min(i, j), 0;
            while(x.judge()) x.div2();
        } else {
            if(y -= x) return x <<= min(i, j), 0;
            while(y.judge()) y.div2();
        }
    }
    return 0;
}

T5又是毕业季2:

题目背景

“叮铃铃铃”,随着高考最后一科结考铃声的敲响,三年青春时光顿时凝固于此刻。毕业的欣喜怎敌那离别的不舍,憧憬着未来仍毋忘逝去的歌。1000多个日夜的欢笑和泪水,全凝聚在毕业晚会上,相信,这一定是一生最难忘的时刻!

题目描述

彩排了一次,老师不太满意。当然啦,取每位同学的号数来找最大公约数显然不太合理。于是老师给每位同学评了一个能力值。于是现在问题变为,从n个学生中挑出k个人使得他们的默契程度(即能力值的最大公约数)最大。但因为节目太多了,而且每个节目需要的人数又不知道。老师想要知道所有情况下能达到的最大默契程度是多少。这下子更麻烦了,还是交给你吧~

PS:一个数的最大公约数即本身。

输入格式

第一行一个正整数n。

第二行为n个空格隔开的正整数,表示每个学生的能力值。

输出格式

总共n行,第i行为k=i情况下的最大默契程度。

输入输出样例

输入 #1复制

4
1 2 3 4

输出 #1复制

4
2
1
1

说明/提示

【题目来源】

lzn原创

【数据范围】

记输入数据中能力值的最大值为inf。

对于20%的数据,n<=5,inf<=1000

对于另30%的数据,n<=100,inf<=10

对于100%的数据,n<=10000,inf<=1e6

#include<iostream>
#include<cstdio>
#include<cmath>
using namespace std;
int a[1000010];
int main()
{
    int n,j,cont=0;
    scanf("%d",&n);
    int i,re;
    double gen;
    for(i=1;i<=n;i++)
    {
        scanf("%d",&re);
        if(re>cont)
        {
            cont=re;
        }
        gen=sqrt(re);
        for(j=1;j<=gen;j++)
        {
            if(re%j==0)
            {
                a[j]++;
                a[re/j]++;
                if((gen-j)<0.000001)
                {
                    a[j]--;
                }
            }
        }
    }
    j=cont;
    for(i=1;i<=n;i++)
    {
        for(;j>=1;j--)
        {
            if(a[j]>=i)
            {
                printf("%d\n",j);
                break;
            }
        }
    }
    return 0;
}

T6斐波那契公约数

题目描述

对于Fibonacci数列:1,1,2,3,5,8,13......大家应该很熟悉吧~~~但是现在有一个很“简单”问题:第n项和第m项的最大公约数是多少?

Update:加入了一组数据。

输入格式

两个正整数n和m。(n,m<=10^9)

注意:数据很大

输出格式

Fn和Fm的最大公约数。

由于看了大数字就头晕,所以只要输出最后的8位数字就可以了。

输入输出样例

输入 #1复制

4 7

输出 #1复制

1

说明/提示

用递归&递推会超时

用通项公式也会超时

#include<cstdio>
#include<iostream>
#include<algorithm>
#define mod 100000000
#define lint long long
using namespace std;
struct Martrix{
    lint mp[3][3];
}; 
lint n,m;
Martrix init,unit,mul;

Martrix __mul(Martrix rec_1,Martrix rec_2){
    Martrix ans;
    for(int i=1;i<=2;i++){
        for(int j=1;j<=2;j++){
            ans.mp[i][j]=0;
        }
    }
    for(int i=1;i<=2;i++){
        for(int j=1;j<=2;j++){
            for(int k=1;k<=2;k++){
                ans.mp[i][j]+=rec_1.mp[i][k]*rec_2.mp[k][j];
                ans.mp[i][j]%=mod;
            }
        }
    } 
    return ans;
}
Martrix __pow(Martrix rec,lint exp){
    Martrix ans=unit;
    while(exp!=0){
        if(exp&1){
            exp-=1;
            ans=__mul(ans,rec);
        }
        exp>>=1;
        rec=__mul(rec,rec);
    } 
    return ans;

lint gcd(lint x,lint y){
    if(x%y==0)return y;
    return gcd(y,x%y);
}
int main(){
    scanf("%lld%lld",&n,&m);
    mul.mp[1][1]=1;
    mul.mp[1][2]=1;
    init.mp[1][1]=0;
    init.mp[1][2]=1;
    init.mp[2][1]=1;
    init.mp[2][2]=1;
    for(int i=1;i<=2;i++){
        for(int j=1;j<=2;j++){
            unit.mp[i][j]=0;
        }
        unit.mp[i][i]=1;
    } 
    lint res=gcd(n,m);
    if(res==1||res==2){
        puts("1");
        return 0;
    }else{
        Martrix ans,tmp=__pow(init,res-2);
        for(int i=1;i<=2;i++){
            for(int j=1;j<=2;j++){
                ans.mp[i][j]=0;
            }
        }
        for(int i=1;i<=2;i++){
            for(int j=1;j<=2;j++){
                for(int k=1;k<=2;k++){
                    ans.mp[i][j]+=mul.mp[i][j]*tmp.mp[k][j];
                    ans.mp[i][j]%=mod;
                }
            }
        }
        printf("%lld",ans.mp[1][2]); 
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值