CodeForces-696C Please(数学题,快速幂取模,乘法逆元)

来源:互联网 发布:域名注册服务商查询 编辑:程序博客网 时间:2024/06/07 09:17

题目链接戳这个:http://codeforces.com/problemset/problem/696/C
题目大意:
Barney闲的蛋疼在玩游戏,他把三个杯子放在桌子上,其中中间那个杯子有个钥匙。Barney从两边的杯子中等概率随机选取一个,跟中间的那个杯子交换,称为一轮操作。问经过n轮操作后,中间的杯子里有钥匙的概率多大?

因为n可能非常大,所以输入一个数组a1,a2,...an,其中n为这个数组的乘积。
输出为x/y,其中x,y互质且是对109+7取模后的值。

题目分析:
高中数学大家都没忘吧,设Pn是n轮操作后中间杯子有钥匙的概率,则第n-1轮的时候,中间杯子里必须没钥匙,且有1/2的概率选到边上那个有钥匙的杯子。故:Pn=(1Pn1)/2.由P0=1,P1=1得,Pn=x/y,其中x=2n(1)n3,y=2n1.
(顺便我在OEIS里面查了,x那个数列叫做Jacobsthal sequence,在组合数学里面是个重要序列。)
Jacobsthal sequence有一个性质,那就是它们都是奇数(很容易证明,因为Jacobsthal序列还有一种递推表示方法是Jn=Jn1+2Jn2,偶数加奇数必为奇数。),而y的因子只有2,故x与y互质没问题。接下来就是解决取模的事情了。
我们可以随着输入(因为题目出的很巧妙,n是数组连乘而不是连加,不然应该是用快速乘法取模)用快速幂取模算法求出2n mod 109+7,那么x可以通过加1或者减1再乘以3的乘法逆元求得,y可以通过乘以2的乘法逆元求得。
离线算出2关于1e9+7的逆元为500000004,3关于1e9+7的逆元为333333336。

AC代码:

#include <bits/stdc++.h>using namespace std;typedef long long ll;const int M=1e9+7;ll qpow(ll a,ll b){    ll res = 1;    while(b){        if(b&1) res = res * a %M;        a = a * a % M;        b >>= 1;    }    return res;}int main() {  int n;  scanf("%d", &n);  ll num,t=2,flag=-1;  while(n--) {    scanf("%I64d", &num);    t=qpow(t,num);    if(num%2==0) //有一个是偶数,则最后乘起来的n就是偶数      flag=1;  }  ll y=t*500000004%M;  ll x=(333333336*(y+flag))%M;  printf("%I64d/%I64d\n",x,y);}

补充:
快速幂取模的模板就是本题的qpow(ll a,ll b)函数,可以求出ab mod M的值。
乘法逆元的概念:
我们都知道,加法,减法,乘法都对取模运算满足分配率,唯独除法不可以。即:
(a+b)%M=a%M+b%M(ab)%M=a%Mb%Mab % M=a%Mb%Ma/b % M a%M/b%M
那么如何处理a/b % M呢?我们可以寻找一个n,使得nb1(mod M),那么就可以把除以b换成乘以n,这个n就称为b关于模M的乘法逆元。寻找这个n就是一个求二元不定方程解的问题,故使用扩展欧几里得算法。这个算法的模板如下:

#include <bits/stdc++.h>const int N=1000000007;int egcd(int a,int b,int &x,int &y){    if(!b) {        x=1;y=0;return a;    }    int ans=egcd(b,a%b,x,y);    int temp=x;    x=y;    y=temp-a/b*y;    return ans;}int cal(int a,int m=N){    int x,y;    int gcd=egcd(a,m,x,y);    if(1%gcd!=0)        return -1;    x*=1/gcd;    m=abs(m);    int ans=x%m;    if(ans<=0)        ans+=m;    return ans;}int main() {  int n;  scanf("%d",&n);  printf("%d关于%d的乘法逆元是%d.\n", n,N,cal(n));}

其中函数cal(int x,int y=M)就是计算x关于y(默认为M=1e9+7)的乘法逆元。

0 0
原创粉丝点击