【数学/扩展欧几里得/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 }

  

时间: 2024-10-26 06:30:06

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

扩展欧几里得定理基础讲解 代码及证明

知识储备 1 . 朴素欧几里得原理:gcd(a,b) == gcd(b,a % b) 2 . 负数取模:忽略符号返回绝对值就好了 3 . 模数原理:对于整数a,b必然存在整数k使得a % b == a - k * b, 且此时k == a / b向下取整 定理内容 对于正整数a,b,必然存在整数(不一定是正数)x,y, 使得ax+by==gcd(x,y) 证明 (来自SDFZ-SPLI的援助) 把两边同时除以gcd(x,y),由朴素欧几里得定理可以得到恒等式,说明一定存在至少一组解使得$ax+b

gcd,扩展欧几里得,中国剩余定理

1.gcd: int gcd(int a,int b){ return b==0?a:gcd(b,a%b); } 2.中国剩余定理: 题目:学生A依次给n个整数a[],学生B相应给n个正整数m[]且两两互素,老师提出问题:有一正整数ans,对于每一对数,都有:(ans-a[i])mod m[i]=0.求此数最小为多少. 输入样例: 1 10 2 3 1 2 3 2 3 5 8 1 2 3 4 5 6 7 8 97 89 67 61 59 53 47 88 12 1 2 3 4 5 6 7 8 9

Uva10673 - Play with Floor and Ceil ( 扩展欧几里定理 )

Uva10673 - Play with Floor and Ceil ( 扩展欧几里定理 )  实际上是一道很裸的扩展欧几里德定理的题目,结果把Floor和Ceil搞反了WA一次悲剧啊 #include <cstdio> #include <cstring> #include <algorithm> #include <cmath> using namespace std; typedef long long LL; void ex_gcd(LL a, L

扩展欧几里得定理

扩展欧几里得定理,很早之前就接触过,没看懂,放弃了,前些天有个有一个题,用扩展欧几里得定理,我竟然都不知道.决定看一下. 看扩展欧几里得定理的最好地方是用维基百科搜索扩展欧几里得算法 就能搜到 照着上面提供第例子走一遍知道什么意思了. 反正主要就是 ax+by=1(mod n) 的x,y值: 还有就是 ax=b(mod n) 这类题的通用解法: 下面粘上一个例子,看完这个例子你就明白了. poj 1061 青蛙的约会 中文题目,我的最爱. 我们设他们跳的步数为step 那么就可以写出算式 n*s

扩展欧几里得定理总结

拓展欧几里得定理主要用来求解同余线性方程,求逆元等,遇到题目给出形如ax+by==c,要求一组满足要求的x和y时,可以联系扩展欧几里得求解 拓展欧几里得由 gcd(a,b) = gcd(b,a%b) 推出 由于 a*x + b*y == gcd(a,b) 必定有解 所以 b*x + (a%b)*y == gcd(b,a%b) 最终得到ax+by==a*y1+b*(x1-(a/b)*y1) 当x0 y0 是方程的一组解,可以得到所有解的形式满足 x=x0+b/d*t y=y0-a/d*t 当 题目

[ACM] hdu 3923 Invoker (Poyla计数,高速幂运算,扩展欧几里得或费马小定理)

Invoker Problem Description On of Vance's favourite hero is Invoker, Kael. As many people knows Kael can control the elements and combine them to invoke a powerful skill. Vance like Kael very much so he changes the map to make Kael more powerful. In

[ACM] hdu 3923 Invoker (Poyla计数,快速幂运算,扩展欧几里得或费马小定理)

Invoker Problem Description On of Vance's favourite hero is Invoker, Kael. As many people knows Kael can control the elements and combine them to invoke a powerful skill. Vance like Kael very much so he changes the map to make Kael more powerful. In

HDU 2669 Romantic (扩展欧几里得定理)

题目大意:给两个数a和b,找出一组x,y使得a*x + b*y = 1,如果找不出输出sorry   题解:显然是用扩展欧几里得定理求解. 又扩展欧几里得定理有,如果a*x+b*y = d   要使得方程有解必有gcd(a,b)为d的约数. 而此题的d = 1  所以若gcd(a,b)!=1,则应该输出sorry #include <bits/stdc++.h> using namespace std; long long e_gcd(long long a,long long b,long

poj1061-青蛙的约会-(贝祖定理+扩展欧几里得定理+同余定理)

青蛙的约会 Time Limit: 1000MS   Memory Limit: 10000K Total Submissions:132162   Accepted: 29199 Description 两只青蛙在网上相识了,它们聊得很开心,于是觉得很有必要见一面.它们很高兴地发现它们住在同一条纬度线上,于是它们约定各自朝西跳,直到碰面为止.可是它们出发之前忘记了一件很重要的事情,既没有问清楚对方的特征,也没有约定见面的具体位置.不过青蛙们都是很乐观的,它们觉得只要一直朝着某个方向跳下去,总能