ZOJ - 4006(数论逆元)

本文提供了一种解决从起点到终点在特定步数内达到指定位置的概率问题的方法。通过数学推导,利用排列组合原理并结合概率计算,最终通过编程实现了解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题解: 求从0点向m走i步那么就得返回i- m步最后原地停留了n+m-2*i步最后用排列组合就是c[n][i]*c[n-i][i-m]*A*B*C

A,B,C分别表示走了i步,i-m步,n+m-2*i步的概率C[n][i] = n!/i!/(n-i)!因为要取膜求一下逆元

最后枚举所有可能的i即可

#include<iostream>
#include<cstring>
#include<algorithm>
#include<queue>
#include<vector>
#include<cstdio>
#include<cmath>
#include<set>
#include<map>
#include<cstdlib>
#include<ctime>
#include<stack>
using namespace std;
#define mes(a) memset(a,0,sizeof(a))
#define rep(i,a,b) for(i = a; i <= b; i++)
#define dec(i,a,b) for(i = b; i >= a; i--)
#define fi first
#define se second
#define ls rt<<1
#define rs rt<<1|1
#define mid (L+R)/2
#define lson ls,L,mid
#define rson rs,mid+1,R
typedef double db;
typedef long long int ll;
typedef pair<int,int> pii;
typedef unsigned long long ull;
const int mx = 1e5+5;
const ll mod = 1e9+7;
ll A[mx];
ll B[mx];
ll modexp(ll x,ll n){
    ll ans = 1;
    while(n){
        if(n&1) ans = ans*x%mod;
        x = x*x%mod;
        n /= 2;
    }
    return ans;
}
int main(){
    A[0] = 1;
    int t;
    for(int i = 1; i < mx; i++)
        A[i] = A[i-1]*i%mod;
    B[0] = B[1] = 1;
    for(int i = 1; i < mx; i++)
        B[i] = modexp(A[i],mod-2);
    scanf("%d",&t);
    while(t--){
        int n,m;
        scanf("%d%d",&n,&m);
        m = abs(m);
        if(n<m){
            puts("0");
            continue;
        }
        if(n==m){
            ll ans = modexp(modexp(4,n),mod-2);
            printf("%lld\n",ans);
            continue;
        }
        ll ans = 0;
        for(int i = m; 2*i <= n+m; i++){
            ll sum = modexp(modexp(4,i),mod-2);
               sum = sum*modexp(modexp(4,i-m),mod-2)%mod;
               sum = sum*modexp(modexp(2,n-2*i+m),mod-2)%mod;
               sum = sum*A[n]%mod*B[i]%mod*B[n-i]%mod;
               sum = sum*A[n-i]%mod*B[i-m]%mod*B[n+m-2*i]%mod;
            ans += sum;
            if(ans>=mod)
                ans -= mod;
        }
        printf("%lld\n",ans);
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值