B题:
思路:
显然概率分析有P=/;因为q次的概率其实是相同的(有放回),对其概率求逆元有: qpow(C(n,k),q,mod)*qpow(C(n+m,k),mod-2,mod);
这里我们使用到了快速幂;其次我们要注意的是求组合数的时候,我发现一开始老是T了;
错误组合数代码:
long long FA(long long a) //定义阶乘函数FA
{
long long b=1;//定义变量b
for(int i=1;i<=a;i++)//计算阶乘
b=(q_mul(b,i,mod))%mod;
return b;//返回值得到b=a!
}
int F(int n,int k)
{
return (FA(n)%mod)/(FA(k)*FA(n-k))%mod;
}
这里我使用该效率高的组合数代码:
const int maxn = 1e6 + 5;
int f(int n,int m){
static int M=0,inv[maxn],mul[maxn],invMul[maxn];
while(M<=n){
if(M){
inv[M]=M==1?1:(mod-mod/M)*inv[mod%M]%mod;
mul[M]=mul[M-1]*M%mod;
invMul[M]=invMul[M-1]*inv[M]%mod;
}
else mul[M]=1,invMul[M]=1;
M++;
}
return mul[n]*invMul[m]%mod*invMul[n-m]%mod;
}
这里给出AC代码:
#include<queue>
#include<iostream>
#include<algorithm>
#include<string.h>
#include<cstdio>
#include <map>
#include<string>
#include<cstring>
#include<iomanip>
#include<set>
#include<map>
#include<numeric>
#include<math.h>
using namespace std;
#define int long long
typedef unsigned long long ull;
typedef double db;
typedef long double ldb;
#define heap priority_queue
#define pll pair<long long, long long>
#define fir first
#define sec second
#define SPO(n) fixed <<setprecision(n)
#define FOR(i, l, r) for (long long i = l; i <= r; ++i)
#define ROF(i, r, l) for (long long i = r; i >= l; --i)
#define endl '\n'
const double pi=3.1415926535;
const double EPS = 1e-9;
const long long MAX = 1e9+5;
int n,sum,m,q,k;
const int mod=1e9+7;
unsigned int q_mul(int a, int b, int mod)//快速乘法
{
unsigned int ans = 0;
while (b)
{
if (b & 1)
{
b--;
ans = (ans + a) % mod;
}
b >>= 1;
a = (a + a) % mod;
}
return ans;
}
int qpow(int a, int n, int mod)//快速幂
{
int ans = 1;
while (n)
{
if (n & 01)ans = ans * a % mod;
a = a * a % mod;
n >>= 1;
}
return ans;
}
//求组合数!!!效率高!!!!
const int maxn = 1e6 + 5;
int f(int n,int m){
static int M=0,inv[maxn],mul[maxn],invMul[maxn];
while(M<=n){
if(M){
inv[M]=M==1?1:(mod-mod/M)*inv[mod%M]%mod;
mul[M]=mul[M-1]*M%mod;
invMul[M]=invMul[M-1]*inv[M]%mod;
}
else mul[M]=1,invMul[M]=1;
M++;
}
return mul[n]*invMul[m]%mod*invMul[n-m]%mod;
}
void Solve(void) {
cin>>n>>m>>k>>q;
if(n==0||k>n)
{
cout<<0<<endl;
return ;
}
int ans1=f(n,k);
int ans2=f(n+m,k);
ans1= qpow(ans1,q,mod);
ans2= qpow(ans2,q,mod);
cout<<ans1*qpow(ans2,(mod-2),mod)%mod<<endl;
return ;
}
signed main() {
std::ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
int t;
cin>>t;
while(t--)
Solve();
}
J题:
题解:
这里我们发现 其实就是 欧拉降幂!!!当然我们只需要特判0^0=1就可以了(前提是要学过欧拉特判),这里我们给出C语言代码:
上AC代码:
#include <bits/stdc++.h>
#define ll long long
#define mod 10000000007
using namespace std;
char a[1000006];
ll x,z;
ll quickpow(ll x,ll y,ll z)
{
ll ans=1;
while(y)
{
if(y&1)
ans=ans*x%z;
x=x*x%z;
y>>=1;
}
return ans;
}
ll phi(ll n)
{
ll i,rea=n;
for(i=2;i*i<=n;i++)
{
if(n%i==0)
{
rea=rea-rea/i;
while(n%i==0)
n/=i;
}
}
if(n>1)
rea=rea-rea/n;
return rea;
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
scanf("%lld %s %lld",&x,a,&z);
ll len=strlen(a);
ll p=phi(z);
ll ans=0;
for(ll i=0;i<len;i++)
ans=(ans*10+a[i]-'0')%p;
ans+=p;
printf("%lld\n",quickpow(x,ans,z));
}
return 0;
}