数学考试 2

45 篇文章 0 订阅
7 篇文章 0 订阅

NOIP2015模拟


这里写图片描述


一、傻牛的递推数列


【问题描述】

傻牛最近钻研各类数学递推数列。尤其是斐波那契数列。
傻牛眼中的斐波那契数列是这样的, F1=1 F2=1 ,然后 Fi+2=Fi+1+Fi ,逐项递推。
今天,傻牛发现,某些斐波那契项之间是成倍数关系的。
例如第 4 F4=3 和第 8 F8=21
傻牛想知道,对于某一项 Fx ,求所有满足 Fi Fx Fi 倍数的 i 的和是多少?


【输入】

输入文件名sequence.in。
输入包含若干组数据,每组数据一行包括一个正整数X,意义如上。


【输出】

输出文件名sequence.out
输出包含若干行,每行对应每组数据的解。


【输入样例】

4


【输出样例】

7


【输入输出解释】

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

【数据范围】

对于 60% 的数据,保证有 X1000000 ,数据组数等于 1
对于 100% 的数据,保证有 X1000000 ,数据组数小于等于 100000


Solution

通过打表,发现答案就为 x 的约数和,当 x 为奇数的时候还要加上 2
所以 ans=p|xp
因为 f(x)=p|xp 为积性函数,所以 ans=ti=1kij=1pji (设 x 的唯一分解式为 pk11×pk22××pktt


Code

#include <iostream>
#include <cstdio>
#include <cmath>

#define LL long long

using namespace std;

LL x,rans;

LL prime[1000010];
bool no_prime[1000010];
LL first[1000010];

void start(){
    for(LL i=2;i<=1000000;i++){
        if(!no_prime[i]){prime[++prime[0]]=i;first[i]=prime[0];}
        for(LL j=1;prime[j]*i<=1000000;j++){
            first[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[first[x]],tt=prime[first[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);

    start();

    while(scanf("%lld",&x)!=EOF){
        work(x,1);
        if(x%2!=0)rans+=2;
        printf("%lld\n",rans);
    }

    return 0;
}

二、傻牛的数字游戏


【问题描述】

傻牛最近在玩一个数字游戏。
首先,规定一个神奇的数字 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 的模值。


【输入样例】

2
1 2
2 2


【输出样例】

2
1


【数据范围】

对于 40% 的数据,保证有 A=1
对于 100% 的数据,保证有 N105 1XP1


Solution

模拟+逆元?!


Code

#include <iostream>
#include <cstdio>

#define LL long long
#define MOD 1000000007

using namespace std;

LL n;

LL ans=1;

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

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

int main(){

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

    n=in();
    while(n--){
        LL x,y;
        x=in();y=in();
        if(x==1){
            ans=ans*y%MOD;
            printf("%lld\n",ans);
        }
        else{
            LL ps=power(y,MOD-2,MOD);
            ans=ans*ps%MOD;
            printf("%lld\n",ans);
        }
    }
    return 0;
}

三、小Y的智力游戏


【问题描述】

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


【输入】

输入文件名为divisor.in。
一行一个整数 N ,意义见上。


【输出】

输出文件名为divisor.out。
一行一个整数,代表傻牛想求出的值。


【输入样例】

4


【输出样例】

8


【样例解释】

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


【数据范围】

对于 50% 的数据,保证有 N103
对于 100% 的数据,保证有 N107


Solution


ans=i=1np|i1=p=1np|i1=p=1np

分块求,可做到 O(n)


Code

#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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值