暑期MQFMATH训练营2

时间:2021-07-14
本文章向大家介绍暑期MQFMATH训练营2,主要包括暑期MQFMATH训练营2使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

Multiply

题目链接

计蒜客 42544

题意

\(Z=a_1!*a_2!*.....*a_n!\)
\(b_i=Z*X^i\)
\(b_i是Y!的一个因子\)
给定n,X,Y的情况下,问i最多能有多大

题解

第一时间想到的就是质因数分解,然后根据质因数的个数去计算,emm.....然后就tle了
这道题求的是i,i是X的幂次,又和Z有关,很容易看出作为多个阶乘的乘积是不能算出来的,所以分解成质因数就成了最好的方法
因为\(b_i是Y!\)的因子,所以把\(Yi\)也分解成质因子的乘积,然后答案就很明显了
对于任意\(Y_i的因子y_i,在Y中有y个,在Z中有z个,在X中有x个,那么i最大就是(y-z)/x了\)
PS:因为数据量很大,所以得用pollard_rho算法,不然会tle

AC代码


#include "bits/stdc++.h"

using namespace  std;
#define int long long
#define ll long long
const int maxn=2e6+10;
const int inf=0x3f3f3f3f;
const int INF=1ll<<62;
inline int rd()
{
    int a;scanf("%lld",&a);return a;
}

int t,n,a[maxn],x,y;
int c1[maxn],c2[maxn],c3[maxn];
int prime[maxn],prime2[maxn],cnt=0,s=0,vis[maxn];


ll gcd(ll a, ll b) {
    return b ? gcd(b, a % b) : a;
}

ll quick_mult(ll a, ll b, ll mod) {
    ll ans = 0;
    while(b) {
        if(b & 1) ans = (ans + a) % mod;
        a = (a + a) % mod;
        b >>= 1;
    }
    return ans;
}
ll quick_pow(ll a, ll n, ll mod) {
    ll ans = 1;
    while(n) {
        if(n & 1) ans = quick_mult(ans, a, mod);
        a = quick_mult(a, a, mod);
        n >>= 1;
    }
    return ans;
}
bool miller_rabin(ll n) {
    if(n == 2) return true;
    if(n < 2 || !(n & 1)) return false;
    ll s = 0, d = n - 1;
    while(!(d & 1)) {
        d >>= 1;
        s++;
    }
    for(int i = 1; i <= 11; i++) {
        ll a = rand() % (n - 2) + 2;
        ll now = quick_pow(a, d, n), pre = now;
        for(int j = 1; j <= s; j++) {
            now = quick_mult(now, now, n);
            if(now == 1 && pre != 1 && pre != n - 1) return false;
            pre = now;
        }
        if(now != 1) return false;
    }
    return true;
}
ll pollard_rho(ll n, int c) {
    ll x, y, i = 1, k = 2;
    x = y = rand() % (n - 2) + 2;
    for( ; ; ) {
        i++;
        x = (quick_mult(x, x, n) + c) % n;
        ll g = gcd(y - x, n);
        if(g > 1 && g < n) return g;
        if(x == y) return n;
        if(i == k) y = x, k <<= 1;
    }
}
void find_fac(ll n, int k) {
    if(n == 1) return ;
    if(miller_rabin(n)) {
        prime[++s]=n;
        return ;
    }
    ll p = n;
    int c = k;
    while(p >= n) p = pollard_rho(p, c--);
    find_fac(p, k);
    find_fac(n / p, k);
}

void init(){
    prime2[++cnt]=prime[1];
    c3[cnt]=1;
    for(int i=2;i<=s;i++){
        if(prime[i]==prime[i-1])c3[cnt]++;
        else prime2[++cnt]=prime[i],c3[cnt]=1;
    }
}

ll cal(ll n,ll x){
    ll ans=0;
    while(n){
        ans+=n/x;
        n/=x;
    }
    return ans;
}

signed main(){
    srand((unsigned)time(NULL));
    t=rd();
    while(t--){
        s=0;cnt=0;
        n=rd();x=rd();y=rd();
        find_fac(x,1111);
        sort(prime+1,prime+1+s);
        init();
        for(int i=1;i<=n;i++){
            a[i]=rd();
        }
        ll ans=4e18;
        for(int i=1;i<=cnt;i++){
            ll num=0;
            for(int j=1;j<=n;j++){
                num+=cal(a[j],prime2[i]);
            }
            ll t=cal(y,prime2[i])-num;
            if(t<0)t=0;
            ans=min(ans,t/c3[i]);
        }
        printf("%lld\n",ans);
        for(int i=1;i<=cnt;i++)c3[i]=0;
    }
    return 0;
}

原文地址:https://www.cnblogs.com/zkpj/p/15013002.html