zoukankan      html  css  js  c++  java
  • allonsy

    时间限制 1s 空间限制 512MB

    2.1 题目描述

    “Allons-y!”
    时间还算足够,好好看看题吧。
    有一种说法,时间线是扭曲的,会相互交织。(一般在科幻片里比较流行?)
    不管啦,反正现在有个蓝盒子,在时间线上随机游走。
    记这个盒子一开始在时间线上的位置为 0,记当前位置为 pos,每一次穿梭,它
    有 q 的概率到达 pos + 1,1 − q 的概率到达 pos − 1。
    特别的,q 是一个有理数。
    我们认为时间线的两端近乎在无穷远处,问 n 次穿梭后,蓝盒子离初始位置的
    期望距离。
    为了避免精度问题,这里采用取模来避免实数运算。
    具体来说,输入会给出一个素数 p,而每次穿梭过程中从 pos 到达 pos + 1 的概
    率 q 将在模意义下给出。(例如 q = ab ,这里保证 b, p 互素,读入的将是模意义下

    的 ab )

    2.2 输入格式

    一行三个正整数 n, q, p,分别表示穿梭的次数、模 p 意义下的概率 q 和模数 p。

    2.3 输出格式

    一行一个整数,为蓝盒子离初始位置的期望距离在模意义下的值。

    2.4 样例输入

    100 1 1000000207

    2.5 样例输出

    100

    42.6 数据规模和约定

    对于全部的数据,10 9 ≤ p ≤ 2 × 10 9 且 p 为素数,0 ≤ q ≤ p − 1
    对于 20% 的数据,n ≤ 15。
    对于另外 30% 的数据,n ≤ 1000。
    对于剩下 50% 的数据,n ≤ 5 × 10 4 。

    【题解】

    这道题我考试时连题目都没看懂。。。

    然而考完后发现此题不难。。。

    *先科普一下费马小定理:
    特别的,当p为素数时,x无法被p整除,φ(p)=p-1,于是便有费马小定理Xp-1≡1(mod p)
    在p是素数时,对任意正整数x都有Xp≡X(mod p)
    于是对于a的逆元x,有ax≡1(mod m),对于a,m互素且m为素数时,有x=am-2,于是我们可以通过快速幂快速求出a的逆元。
    另外,借助素数筛,我们还可以很快的求出1-n的欧拉函数值。每当我们找到一个素数,就把他的倍数的欧拉函数值乘上(p-1)/p.
    而且,借助费马小定理我们可以实现对除法取模。*

    这道题的模意义下,指的是把除法变成乘法,把a/b变成a*(1/b),而1/b是b的逆元。

    这道题就变成数学问题了。

    公式为f[n]=∑(n i=0)q^i*(1-q)^(n-i)C(n,i)|n−2×i|

    然而我似乎不太理解这个公式,有时间再看吧。。(逃~~)

    #include<iostream>
    #include<cmath>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    #include<vector>
    #define ll (long long)
    #define re register
    #define il inline
    #define fp(i,a,b) for(re int i=a;i<=b;i++)
    #define fq(i,a,b) for(re int i=a;i>=b;i--)
    using namespace std;
    const int Maxn=50005;
    int n,q,p;
    int fac[Maxn],ifac[Maxn],pw[Maxn];//fac阶乘 ifac阶乘逆元
    il int gi()
    {  
      re int x=0;
      re short int t=1;
      re char ch=getchar();
      while((ch<'0'||ch>'9')&&ch!='-') ch=getchar();
      if(ch=='-') t=-1,ch=getchar();
      while(ch>='0'&&ch<='9') x=x*10+ch-48,ch=getchar();
      return x*t;
    }
    int qp(int a,int x)
    {
        int ret=1;
        for (;x;x>>=1,a=ll(a)*a%p)
            if (x&1) ret=ll(ret)*a%p;
        return ret;
    }
    int c(int n,int k)
    {
        return ll(fac[n])*ifac[k]%p*ifac[n-k]%p;
    }
    int main()
    {
        //freopen("allonsy.in", "r", stdin);
    //  freopen("allonsy.out", "w", stdout);
        n=gi();q=gi();p=gi();
        fac[0]=1;
        fp(i,1,n)
            fac[i]=ll(fac[i-1])*i%p;//预处理i的阶乘
        ifac[n]=qp(fac[n],p-2);//ifac[i]=fac[i]的负一次方 在模P意义下同等于fac[N]的P-2次方 此即费马小定理
        fq(i,n-1,0)
            ifac[i]=ifac[i+1]*ll(i+1)%p;//预处理i的阶乘逆元
        fp(i,0,n) pw[i]=1;
        int q0=1,q1=1;
        fp(i,1,n)
        {
            q0=q0*ll(q)%p;
            q1=q1*ll(1+p-q)%p;
            pw[i]=ll(pw[i])*q0%p;
            pw[n-i]=ll(pw[n-i])*q1%p;
        }
        int ans=0;
        fp(i,0,n)
            ans=(ans+ll(c(n,i))*pw[i]%p*abs(2*i-n))%p;
            //abs(2*i-n)为离原点距离
            //c用于求组合数
        printf("%d
    ",ans);
        return 0;
    } 
  • 相关阅读:
    【简单算法】27.验证二叉搜索树
    【简单算法】26. 二叉树的最大深度
    【简单算法】25. 环形链表
    pandas 数据处理
    主成分分析 PCA
    hive 导出数据到本地
    深度学习的优化方法 总结
    ALS算法 (面试准备)
    Bagging和Boosting的区别(面试准备)
    ROC 曲线,以及AUC计算方式
  • 原文地址:https://www.cnblogs.com/yanshannan/p/7375733.html
Copyright © 2011-2022 走看看