您的位置:首页 > 其它

古代猪文 [Sdoi2010][Codevs 1830]

2016-06-16 09:19 197 查看

题目描述 Description

[背景]

“在那山的那边海的那边有一群小肥猪。他们活泼又聪明,他们调皮又灵敏。他们自由自在生活在那绿色的大草坪,他们善良勇敢相互都关心……”

——选自猪王国民歌

很久很久以前,在山的那边海的那边的某片风水宝地曾经存在过一个猪王国。猪王国地理位置偏僻,实施的是适应当时社会的自给自足的庄园经济,很少与外界联系,商贸活动就更少了。因此也很少有其他动物知道这样一个王国。

猪王国虽然不大,但是土地肥沃,屋舍俨然。如果一定要拿什么与之相比的话,那就只能是东晋陶渊明笔下的大家想象中的桃花源了。猪王勤政爱民,猪民安居乐业,邻里和睦相处,国家秩序井然,经济欣欣向荣,社会和谐稳定。和谐的社会带给猪民们对工作火红的热情和对未来的粉色的憧憬。

小猪iPig是猪王国的一个很普通的公民。小猪今年10岁了,在大肥猪学校上小学三年级。和大多数猪一样,他不是很聪明,因此经常遇到很多或者稀奇古怪或者旁人看来轻而易举的事情令他大伤脑筋。小猪后来参加了全猪信息学奥林匹克竞赛(Pig Olympiad in Informatics, POI),取得了不错的名次,最终保送进入了猪王国大学(Pig Kingdom University, PKU)深造。

现在的小猪已经能用计算机解决简单的问题了,比如能用P++语言编写程序计算出A + B的值。这个“成就”已经成为了他津津乐道的话题。当然,不明真相的同学们也开始对他刮目相看啦~

[描述]

猪王国的文明源远流长,博大精深。

iPig在大肥猪学校图书馆中查阅资料,得知远古时期猪文文字总个数为 N 。当然,一种语言如果字数很多,字典也相应会很大。当时的猪王国国王考虑到如果修一本字典,规模有可能远远超过康熙字典,花费的猪力、物力将难以估量。故考虑再三没有进行这一项劳猪伤财之举。当然,猪王国的文字后来随着历史变迁逐渐进行了简化,去掉了一些不常用的字。

iPig打算研究古时某个朝代的猪文文字。根据相关文献记载,那个朝代流传的猪文文字恰好为远古时期的k分之一,其中k是N的一个正约数(可以是 1 和 N )。不过具体是哪 k 分之一,以及 k 是多少,由于历史过于久远,已经无从考证了。

iPig觉得只要符合文献,每一种能整除 N 的 k 都是有可能的。他打算考虑到所有可能的 k 。显然当 k 等于某个定值时,该朝的猪文文字个数为 Nk 。然而从 N 个文字中保留下 Nk 个的情况也是相当多的。iPig预计,如果所有可能的 k 的所有情况数加起来为 P 的话,那么他研究古代文字的代价将会是 G 的 P 次方。

现在他想知道猪王国研究古代文字的代价是多少。由于iPig觉得这个数字可能是天文数字,所以你只需要告诉他答案除以 999911659 的余数就可以了。

输入描述 Input Description

输入有且仅有一行:两个数 N、G ,用一个空格分开。

输出描述 Output Description

输出有且仅有一行:一个数,表示答案除以 999911659 的余数。

样例输入 Sample Input

4 2

样例输出 Sample Output

2048

数据范围及提示 Data Size & Hint

10% 的数据中, 1≤N≤50;

20% 的数据中, 1≤N≤1000;

40% 的数据中, 1≤N≤100000 ;

100% 的数据中, 1≤G≤1000000000,1≤N≤1000000000 。

分析

令 m=999911659

根据题目不难得出 ans=G∑k|nCknmodm

但是这个 ans 并不好求。首先因为 Cknmodm=n!k!(n−k)!modm=n!(k!)−1[(n−k)!]−1modm

其中 x−1∗x≡1(modm)。

又 ∵(k!)−1∗(k!)≡1(modm),[(k+1)!]−1∗[(k+1)]!≡1(modm) ∴(k+1)(k!)−1∗(k!)≡(k+1)[(k+1)!]−1∗[(k+1)]!(modm) ∴(k+1)!(k!)−1≡(k+1)[(k+1)!]−1∗[(k+1)]!(modm) ∴(k!)−1≡(k+1)[(k+1)!]−1(modm)

因为 m 是质数 ∴km−1≡1(mod m)

故 (k!)−1 可以线性求出

又 ∵GP(mod m))≡GP(mod φ(m))+φ(m)∵φ(m)=2∗3∗4679∗35617

令 x=Ckn(mod φ(m))

⎧⎩⎨⎪⎪⎪⎪⎪⎪⎪⎪xxxx≡Ckn(mod 2)≡Ckn(mod 3)≡Ckn(mod 4679)≡Ckn(mod 35617)

利用孙子定理(孙子定理不会?百度上有!) 解出 x 即可

代码

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

typedef long long LL ;

const LL Size = 40000;
const LL Mod = 999911659;
const LL Mod2 = 999911658;
const LL p[] = {4679,3,2,35617};
const LL t[] = {1353,1,1,31254};

LL f[Size][4];
LL g[Size][4];

LL Lucas(LL,LL,LL);
LL pow(LL,LL,LL);
LL get(LL,LL,LL,LL);
void init(LL);

int main(){

init(Size-1);

LL n,r;

scanf("%lld%lld",&n,&r);

LL ans = 0;
for(LL i=1;i<sqrt(n);++i)
if(n%i == 0)
ans = (ans+get(Lucas(i,n,0),Lucas(i,n,1),Lucas(i,n,2),Lucas(i,n,3))+get(Lucas(n/i,n,0),Lucas(n/i,n,1),Lucas(n/i,n,2),Lucas(n/i,n,3)))%Mod2;
if(((LL)sqrt(n))*sqrt(n) == n)
ans = (ans+get(Lucas(sqrt(n),n,0),Lucas(sqrt(n),n,1),Lucas(sqrt(n),n,2),Lucas(sqrt(n),n,3)))%Mod2;

printf("%lld\n",pow(r,ans+Mod-1,Mod));

return 0;

}

void init(LL x){

f[0][0] = f[0][1] = f[0][2] = f[0][3] = 1;
for(LL i=1;i<x;++i)
for(LL j=0;j<4;++j)
f[i][j] = f[i-1][j]*i%p[j];

for(LL i=0;i<4;++i)
g[p[i]-1][i] = pow(f[p[i]-1][i],p[i]-2,p[i]);
for(LL i=x-1;i>=0;--i)
for(LL j=0;j<4;++j)
if(i<p[j]-1)
g[i][j] = g[i+1][j]*(i+1)%p[j];

}

LL Lucas(LL x,LL y,LL i){

LL mod = p[i];

if(x > y)
return 0;
if(!x)
return 1;
if(y >= mod)
return (Lucas(x/mod,y/mod,i)*Lucas(x%mod,y%mod,i))%mod;
else
return f[y][i]*g[x][i]%mod*g[y-x][i]%mod;

}

LL get(LL a,LL b,LL c,LL d){
return (a*t[0]%Mod2*Mod2/p[0]%Mod2+b*t[1]%Mod2*Mod2/p[1]%Mod2+c*t[2]%Mod2*Mod2/p[2]%Mod2+d*t[3]%Mod2*Mod2/p[3]%Mod2)%Mod2;
}

LL pow(LL x,LL y,LL mod){

LL ans = 1;
while(y){
if(y&1)
ans = ans*x%mod;
x = x*x%mod;
y >>= 1;
}

return ans;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  数学