挑战nbc (noip2016)膜你赛Day1提高组

来源:互联网 发布:淘宝可以货到付款吗? 编辑:程序博客网 时间:2024/05/21 14:43
挑战 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 mod1000000007=x 的整数。(其实就是分数取模辣)
【输入样例 1】
2
【输出样例 1】
500000005
【样例 1 说明】
显然答案是 3/2,500000005*2 mod 1000000007=3
【输入输出样例 2】
见选手目录下的 nbc/nbc2.in 和 nbc/nbc2.out
【送温暖】
根据费马小定理,你最后输出的应该是 x*y^1000000005
mod 1000000007

【限制与约定】















有些大佬好像用了矩阵乘法,好吧,我来讲讲我用的一个比较简单的方法

在操作了 n-1 次之后,要使最后剩下的那道题难度最大,我试了试一些数据,可以惊奇地发现每次合并的两个肯定是最小的两个。我是找规律的,求大神教证明。

那么可以得出ans = (n - 1) * 2^(n-1) + 1 / 2^(n - 1)

分母的质因数只有2,而分子是奇数,所以这是最简分数,所以 x = (n - 1) * 2^(n-1) + 1,y =  2^(n - 1)

善良的出题人已经送温暖了,所以只要求 x*y^1000000005 mod 1000000007就行了。但n最大是10^9。

我就用了一个时间差不多为O(log2n的算法

程序比较粗糙,还是pascal快哭了

var n, p: longint;     t1, t2: int64; function two(x: longint): int64; var xx: int64; begin    if x = 1 then        exit(2);     if odd(x) = false then    begin        xx := two(x div 2) mod p;         exit(xx * xx mod p);     end    else exit(two(x - 1) * 2 mod p); end; function other(x: longint): int64; var xxx: int64; begin    if x = 1 then        exit(t1);     if odd(x) = false then    begin        xxx := other(x div 2) mod p;         exit(xxx * xxx mod p);     end    else exit(other(x - 1) * t1 mod p); end; begin    readln(n);     p := 1000000007;     t1 := two(n - 1); //求2^(n-1) mod p,也就是y mod p    t2 := other(1000000005); //求y^1000000005 mod p    t1 := (t1 * (n - 1) + 1) mod p; //求(n-1)*2^(n-1)+1 mod p    writeln(t1 * t2 mod p); end. 

//中间多mod mod p 也是好的,不影响结果,也不会超范围


原创粉丝点击