0
点赞
收藏
分享

微信扫一扫

哈尔滨理工大学第12届程序设计竞赛(牛客)题解

左小米z 2022-04-03 阅读 53
c++算法

 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;
}

 

 

 

举报

相关推荐

0 条评论