挑战nbc
题目描述:
Abwad是一名有志向的优秀OI少年。遗憾的是,由于高能宇宙射线的影响,他不幸在NOI中滚粗。不过,Abwad才高一,还有许许多多的机会。在长时间的刻苦学习之后,他实力大增,并企图撼动OI界魔王nbc的权威。
这一天,Abwad决定挑战nbc。挑战的项目是OI界一种常见的运动:造题,比的就是谁造得又快又好。Abwad现在拿到了难度为1,2,3,……,n的n道原题,每次操作他可以挑出任意两道题,并使用一种叫做“NOIP二合一”的方法合成一道难度为其平均值的题。Abwad希望在操作了n-1次之后,最后剩下的那道题难度最大。
输入格式:
一行一个整数,表示n。
输出格式:
一行一个整数ans,若答案的最简分数为x/y,ans应为最小的满足ans*y mod 1000000007=x的整数。(其实就是分数取模辣)
样例输入:
样例1: 2 样倒2: 100
样例输出:
样例1: 500000005 样例2: 958557238
提示:
【样例1说明】
显然答案是3/2,500000005*2 mod 1000000007=3
【可能用到的知识】
费马小定理:当p是质数时,ap-1 mod p=1
时间限制:1000ms空间限制:256MByte
这个题目是在初步学习数论之后的第一个和目前数论知识能够比较接轨的题目。因为是随机生成的数据,所以我暴力做法都能够拿到70分。但是这并不是正解,就不贴上来了。然后我们将这个问题拆成两个问题,一:求x/y,二:求ans。第一个问题的话应该很好解决,应该先加最小的,最后加最大的,然后这个部分直接模拟应该就可以了。但是其实很明显,这个会超时的,所以我们需要寻找通项公式,先找x,当n=1,2,3,4……时,x=1,3,9,25……。然后根据数学归纳法可以知道x的通项公式x=(n-1)*2(n-1)+1,同理可得y=2(n-1),然后ans=x/y(mod p) 然后1/y可以由逆元得出(逆元+费马小定理)1/y=y(p-2)再将y的逆元乘x即可得到ans。
#include<bits/stdc++.h> using namespace std; const long long P=1000000007; long long n,x,y,ans; int fastpow(int a,int b){ long long r=1,base=a; while (b){ if (b&1) r=(r*base)%P; base=(base*base)%P; b>>=1; } return r; } int main(){ cin>>n; x=fastpow(2,n-1); x=(x*(n-1)+1)%P; y=fastpow(2,n-1); ans=x*fastpow(y,P-2)%P; cout<<ans; return 0; }
身为一个数论渣渣,第一写一个数论题目的题解,还有一点小激动。