数学考试2(test20170311)

【傻牛的递推数列】(sequence.pas/c/cpp Time:1s Memory:256M)

【问题描述】

傻牛最近钻研各类数学递推数列。尤其是斐波那契数列。

傻牛眼中的斐波那契数列是这样的,F1=1,F2=1 ,然后Fi+2=Fi+1+Fi ,逐项递推。

今天,傻牛发现,某些斐波那契项之间是成倍数关系的。例如第4项F4=3 和第8项F8=21 。傻牛想知道,对于某一项Fx ,求所有满足FiFxFi 倍数的i的和是多少?

【输入】

输入文件名sequence.in。

输入包含若干组数据,每组数据一行包括一个正整数X,意义如上。

【输出】

输出文件名sequence.out

输出包含若干行,每行对应每组数据的解。

【输入输出样例】

Sequence.in
4
Sequence.out
7
【输入输出解释】

F1 ,F2 ,F4F4 的约数,所以权值为1+2+4=7

【数据范围】

对于60%的数据,保证有X≤1000000,数据组数等于1。

对于100%的数据,保证有X≤1000000,数据组数小于等于100000。

【题解】

反正对于数学题,首先就是打暴力,再打表,然后再找规律,这个题也不例外,经打表可以发现答案就为 x 的约数和,当 x 为奇数的时候还要加上 2。

所以问题转化为求一个数的约数和即可

关于求约数和,有约数和公式:

对于已经分解的整数

A=p1k1×p2k2×p3k3××pnkn

有A的所有因子之和为

S=(1+p1+p12+p13++p1k1)×(1+p2+p22+p23++p2k2)×(1+p3+p32+p33++p3k3)×(1+pn+pn2+pn3++pnkn)

【代码】

#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <iostream>
using namespace std;

const int size = 1000010;
typedef long long LL;
LL n,rans,prime[size],fir[size];
bool no_prime[size];

void pre_prime() {
    for(LL i=2;i<=size;i++){
        if(!no_prime[i]) {
            prime[++prime[0]]=i;fir[i]=prime[0];
        }
        for(LL j=1;prime[j]*i<=size;j++){
            fir[prime[j]*i]=j;
            no_prime[prime[j]*i]=true;
            if(i%prime[j]==0)break;
        }
    }
}

void work(LL x,LL ans){
    if(x==1) {
        rans=ans;return;
    }
    LL tmp=prime[fir[x]],tt=prime[fir[x]],equ=1;
    while(x%tmp==0) {
        equ+=tt;
        tt=tt*tmp;
        x/=tmp;
    }
    work(x,ans*equ);
}

int main() {
    freopen("sequence.in","r",stdin);
    freopen("sequence.out","w",stdout);
    pre_prime();
    while(~scanf("%lld",&n)) {
        work(n,1);
        if(n&1)
            rans+=2;
        printf("%lld\n",rans);
    }
    return 0;
}

【傻牛的数字游戏】(Game.pas/c/cpp Time:1s Memory:256M)

【问题描述】

傻牛最近在玩一个数字游戏。

首先,规定一个神奇的数字P,它就是1000000007。

这个游戏是这样的,首先给你一个无比巨大的数字1000000006!1000000006 ,当然,这个数字对P的模值为1。然后,游戏可能给你以下两种操作之一,第一种操作就是将这个数乘以一个数字X,第二种操作就是将这个数字除以一个数字X。要求输出每种操作过后这个数字对P的模值。现在,傻牛的菊花痒了,要去上厕所了,你不得不帮他玩一盘。

【输入】

输入文件名Game.in。

一行一个数字N代表操作总数。

接下N行代表顺次的N个操作,每个操作占一行,按“A X”格式给出,A=1时代表操作1,A=2时代表操作2。

【输出】

输出文件名Game.out。

输出包含N行,每行对应这个操作结束时这个数字对P的模值。

【输入输出样例】

Game.in
2
1 2
2 2
Game.out
2
1
【数据范围】

对于40%的数据,保证有A=1。

对于100%的数据,保证有N1051XP1

【题解】

我们可以一眼看出A=1的时候就是将答案直接乘上X即可,轻松40分。(为什么的话自行度娘)

然后其实100分的话也好拿,学了逆元的话直接秒掉,总之这题水的一B。

【代码】

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

const int MOD = 1000000007;
typedef long long LL;
LL n,ans=1;

LL ksm(LL x,LL y,LL Mod);
LL read();

int main() {
    freopen("game.in","r",stdin);
    freopen("game.out","w",stdout);
    n=read();
    for(LL i=1,op,x;i<=n;i++) {
        op=read();x=read();
        if(op==1){
            ans=ans*x%MOD;
            printf("%lld\n",ans);
        }
        else{
            LL ret=ksm(x,MOD-2,MOD);
            ans=ans*ret%MOD;
            printf("%lld\n",ans);
        }
    }
    return 0;
}

LL ksm(LL x,LL y,LL Mod) {
    x%=Mod;
    LL ret=1;
    while(y){
        if(y&1)
            ret=ret*x%Mod;
        x=x*x%Mod;
        y>>=1;
    }
    return ret;
}

LL read() {
    LL ans=0;
    char ch=getchar();
    while(ch<'0'||ch>'9')
        ch=getchar();
    while(ch>='0'&&ch<='9') {
        ans=ans*10+ch-'0';ch=getchar();
    }
    return ans;
}

【傻牛的约数研究】(divisor.pas/c/cpp Time:1s Memory:256M)

【问题描述】

傻牛最近在研究约数,它觉得这玩意很牛逼。

首先,对于一个数字X来说,设F(X) 表示X的约数个数,可以先将X表达成为若干个质数的幂次之积,即X=p1k1×p2k2××psks ,然后F(X)=(k1+1)×(k2+1)××(ks+1) 。傻牛觉得这个碉堡了。有一天它想,我们是不是可以求出F(1)+F(2)+F(3)++F(N) 的值呢?结果,它晕掉了。

【输入】

输入文件名为divisor.in。

一行一个整数N,意义见上。

【输出】

输出文件名为divisor.out。

一行一个整数,代表傻牛想求出的值。

【输入输出样例】

Divisor.in
4
Divisor.out
8
【样例解释】

F(1)+F(2)+F(3)+F(4)=1+2+2+3=8 .

【数据范围】

对于50%的数据,保证有N≤103。

对于100%的数据,保证有N≤106。

【题解】

这题目还可以再水一些,核心代码只有四行就可以A掉此题,不要问我为什么,因为我也不知道。。。

核心代码:

scanf("%d",&n);
for(int i=1;i<=n;i++)
ans+=n/i;
printf("%d\n",ans);

【代码】

该代码为pyh的分块代码,据说可以降到O(n) 了。

#include <iostream>
#include <cstdio>

#define LL long long

using namespace std;

LL x,ans;

int main(){

    freopen("divisor.in","r",stdin);
    freopen("divisor.out","w",stdout);

    scanf("%lld",&x);

    for(LL i=1,it;i<=x;i=it+1){
        it=x/(x/i);
        ans+=(x/i)*(it-i+1);
    }

    printf("%lld\n",ans);

    return 0;
}

总结

今天的考试是今年第一次AK,值得庆祝,不过主要是因为题目还是有点水了,下午的考试于是就GG了。。。

发布了39 篇原创文章 · 获赞 7 · 访问量 1万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章