这道题题意为给两个数,有n位,数是m进制,为零的位置可以填入1到m的任何数,求第一个数大于第二个数个概率
设概率为x/y,这题答案为(x/y)%mod,可以拆成两部分x%mod*(1/y)%mod,x%mod部分可以用dp推出
,(1/y)%mod的部分可以用n*y=1(%mod)求出答案就是n,n就是y关于mod的逆元
逆元可以由费马小定理得出结论n=y^(mod-2);
也可以用欧几里得定理
1 #include <iostream> 2 #include <string.h> 3 #include <stdlib.h> 4 #include <stdio.h> 5 #include <math.h> 6 using namespace std; 7 const int INF = 0x3f3f3f3f; 8 typedef long long LL; 9 10 void extra_gcd(LL a, LL b, LL &x, LL &y, LL &d) 11 { 12 if(b == 0) 13 { 14 d = a; 15 x = 1; 16 y = 0; 17 } 18 else 19 { 20 extra_gcd(b, a%b, y, x, d); 21 y -= (a/b) * x; 22 } 23 } 24 25 int main() 26 { 27 LL a, b, p, x, y, d; 28 scanf("%lld%lld%lld", &a, &b, &p); 29 extra_gcd(b, p, x, y, d); 30 x = (x + p) % p; 31 printf("%lld\n", (a * x) % p); 32 return 0; 33 }
题目的代码
#include <iostream> #include <string.h> #include <stdlib.h> #include <stdio.h> #include <math.h> using namespace std; #define INF = 0x3f3f3f3f #define MST(vis,x) memset(vis,x,sizeof(vis)) #define ll long long #define maxn 100005 const ll mod=1e9+7; ll a[maxn]; ll b[maxn]; ll dp[maxn][2];//dp[x][0]代表相等,dp[x][1]代表大于 ll quickpow(ll x,ll y) { ll ans=1; while(y>0) { if(y&1)ans=ans*x%mod; x=x*x%mod; y/=2; } return ans; } int main() { ll n,m; while(scanf("%lld%lld",&n,&m)!=EOF) { for(int i=1;i<=n;i++)scanf("%lld",&a[i]); for(int i=1;i<=n;i++)scanf("%lld",&b[i]); MST(dp,0); dp[0][0]=1; ll all=0; for(int i=1;i<=n;i++) { if(a[i]==0)all++; if(b[i]==0)all++; if(a[i]&&b[i]) { if(a[i]==b[i]) { dp[i][0]=dp[i-1][0]; dp[i][1]=dp[i-1][1]; } else if(a[i]>b[i]) { dp[i][1]=(dp[i-1][1]+dp[i-1][0])%mod; dp[i][0]=0; } else { dp[i][1]=dp[i-1][1]; dp[i][0]=0; } } else if(a[i]==0&&b[i]==0) { dp[i][0]=dp[i-1][0]*m%mod; dp[i][1]=(dp[i-1][1]*(m*m%mod)%mod+dp[i-1][0]*((m*(m-1)/2)%mod)%mod)%mod; } else if(a[i]==0) { dp[i][0]=dp[i-1][0]%mod; dp[i][1]=(dp[i-1][1]*m%mod+dp[i-1][0]*(m-b[i])%mod)%mod; } else if(b[i]==0) { dp[i][0]=dp[i-1][0]%mod; dp[i][1]=(dp[i-1][1]*m%mod+dp[i-1][0]*(a[i]-1)%mod)%mod; } } cout << dp[n][1]*quickpow(quickpow(m,all),mod-2)%mod << endl; } return 0; }