【数学/扩展欧几里得/Lucas定理】BZOJ 1951 :[Sdoi 2010]古代猪文


 

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等于某个定值时,该朝的猪文文字个数为N / k。然而从N个文字中保留下N / k个的情况也是相当多的。iPig预计,如果所有可能的k的所有情况数加起来为P的话,那么他研究古代文字的代价将会是G的P次方。 现在他想知道猪王国研究古代文字的代价是多少。由于iPig觉得这个数字可能是天文数字,所以你只需要告诉他答案除以999911659的余数就可以了。

Input

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

Output

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

  首先来理解一下题意:我们有一个数N,他有因数{p1,p2,p3..pcnt},求(G^)%mod
  根据费马小定理,我们把它分解为G^(%(mod-1))%mod
  由于mod-1不是质数,不能用费马小定理求逆元。。
  所以我们把它分解成4个方程。分解(mod-1)得(2,3,4679,35617)。
  我们设s=
  则相当于解s ≡ a1 (mod 2)
       s ≡ a2 (mod 3)
       s ≡ a3 (mod 4679)
       s ≡ a4 (mod 53617)
  设s%(mod-1)答案是x  
       x ≡ a1 (mod 2)
       x ≡ a2 (mod 3)
       x ≡ a3 (mod 4679)
       x ≡ a4 (mod 53617)
  然后就是喜闻乐见的中国剩余定理了。。
  组合数用Lucas去弄,设定一个fac[i][j]表示mo[i](i<=4)1*2*3*..*j的值(不会大于mo[i],否则一直是0)。
  逆元用exgcd。
  
 1 #include<cstdio>
 2 #include<cstring>
 3 #include<cmath>
 4 #include<algorithm> 
 5 
 6 #define mo 999911659
 7 
 8 typedef long long ll;
 9 
10 using namespace std;
11 
12 int mod[5]={0,2,3,4679,35617};
13 
14 ll w[5],fac[5][36001];
15 
16 ll Qvod(ll x,ll k,ll mod)
17 {
18     ll ans=1;
19     while(k!=0)
20     {
21         if(k&1)ans=ans*x%mod;
22         x=x*x%mod;
23         k>>=1;
24     }
25     return ans;
26 }
27 
28 ll C(ll x,ll k,ll m)
29 {
30     if(x<k)return 0;
31     return fac[m][x]*Qvod(fac[m][k]*fac[m][x-k],mod[m]-2,mod[m])%mod[m];
32 }
33 
34 ll Lucas(ll x,ll k,int m)
35 {
36     if(x==0)return 1;
37     return Lucas(x/mod[m],k/mod[m],m)*C(k%mod[m],x%mod[m],m)%mod[m];
38 }
39 
40 ll x,y;
41 
42 void exgcd(ll n,ll m)
43 {
44     if(m==0){x=1,y=0;return;}
45     exgcd(m,n%m);
46     ll t=x;x=y,y=t-n/m*y;
47 }
48 
49 ll solve()
50 {
51     ll ans=0;
52     for(int i=1;i<=4;i++)
53     {
54         ll sb=(mo-1)/mod[i];
55         exgcd(sb,mod[i]);
56         ans=(ans+x*sb*w[i])%(mo-1);
57     }
58     if(ans<=mo-1)ans+=(mo-1);
59     return ans;
60 }
61 
62 int main()
63 {
64     for(int i=1;i<=4;i++)
65     {
66         fac[i][0]=1;
67         for(int j=1;j<=mod[i];j++)
68             fac[i][j]=fac[i][j-1]*j%mod[i];
69     }
70     int n,g;
71     scanf("%d%d",&n,&g);
72     if(g==mo){printf("0");return 0;}
73     g%=mo;
74     for(int i=1;i<=sqrt(n);i++)
75     {
76         if(n%i==0)
77         {
78             int tmp=n/i;
79             for(int j=1;j<=4;j++){
80                 if(tmp!=i)w[j]=(w[j]+Lucas(tmp,n,j));
81                 w[j]=(w[j]+Lucas(i,n,j))%mod[j];
82             }
83         }
84     }
85     printf("%lld",Qvod(g,solve(),mo));
86     return 0;
87 }
View Code

 

  
posted @ 2015-07-07 20:44  puck_just_me  阅读(187)  评论(0编辑  收藏  举报