NOIP2015模拟
一、傻牛的递推数列
【问题描述】
傻牛最近钻研各类数学递推数列。尤其是斐波那契数列。
傻牛眼中的斐波那契数列是这样的,
F1=1
,
F2=1
,然后
Fi+2=Fi+1+Fi
,逐项递推。
今天,傻牛发现,某些斐波那契项之间是成倍数关系的。
例如第
4
项
傻牛想知道,对于某一项
Fx
,求所有满足
Fi
是
Fx
是
Fi
倍数的
i
的和是多少?
【输入】
输入文件名sequence.in。
输入包含若干组数据,每组数据一行包括一个正整数X,意义如上。
【输出】
输出文件名sequence.out
输出包含若干行,每行对应每组数据的解。
【输入样例】
4
【输出样例】
7
【输入输出解释】
【数据范围】
对于
60%
的数据,保证有
X≤1000000
,数据组数等于
1
。
对于
Solution
通过打表,发现答案就为
x
的约数和,当
所以
因为
f(x)=∑p|xp
为积性函数,所以
ans=∏ti=1∑kij=1pji
(设
x
的唯一分解式为
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
,它就是
这个游戏是这样的,首先给你一个无比巨大的数字
(1000000006!)1000000006
,当然,这个数字对
P
的模值为
然后,游戏可能给你以下两种操作之一,第一种操作就是将这个数乘以一个数字
X
,第二种操作就是将这个数字除以一个数字
要求输出每种操作过后这个数字对
P
的模值。
现在,傻牛的菊花痒了,要去上厕所了,你不得不帮他玩一盘。
【输入】
输入文件名Game.in。
一行一个数字
接下
N
行代表顺次的
【输出】
输出文件名Game.out。
输出包含
【输入样例】
2
1 2
2 2
【输出样例】
2
1
【数据范围】
对于
对于
100%
的数据,保证有
N≤105
,
1≤X≤P−1
。
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(1)+F(2)+F(3)+……+F(N)
的值呢?
结果,它晕掉了。
【输入】
输入文件名为divisor.in。
一行一个整数
N
,意义见上。
【输出】
输出文件名为divisor.out。
一行一个整数,代表傻牛想求出的值。
【输入样例】
4
【输出样例】
8
【样例解释】
【数据范围】
对于
50%
的数据,保证有
N≤103
。
对于
100%
的数据,保证有
N≤107
。
Solution
分块求,可做到 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;
}