1. 程式人生 > >牛客小白月賽6 水題 求n!在m進制下末尾0的個數 數論

牛客小白月賽6 水題 求n!在m進制下末尾0的個數 數論

int deb 技術分享 end class coder 計算 min with

鏈接:https://www.nowcoder.com/acm/contest/135/C
來源:牛客網

題目描述

技術分享圖片 其中,f(1)=1;f(2)=1;Z皇後的方案數:即在Z×Z的棋盤上放置Z個皇後,使其互不攻擊的方案數。

輸入描述:

輸入數據共一行,兩個正整數x,m,意義如“題目描述”。

輸出描述:

一個正整數k,表示輸出結尾0 的個數或者放置皇後的方案數
示例1

輸入

復制
375 16

輸出

復制
14200

說明

技術分享圖片 鳴謝真·dalao Tyxao 分析:打表題目中的公式容易得到:f(n) = f(n-1) + f(n-2) (n>=3) 因為x最大取到10^18,所以我們打表前90位就可以了
  然後判斷x是否等於前九十項中一項的值,如果等於就計算x!在m進制下末尾0的個數,如果不等於輸出a[x%min(13,m)+1],a數組13*13棋盤下每種皇後的個數(類似八皇後,dfs求就可以了)   重點來看x!在m進制下末尾0的個數   十進制下:500 = 5*10^2 五進制下: 300 = 3*5^2   所以:m進制下:x = a*m^k,因為任意一個大於1的數都可以表示為幾個質數的乘積   所以:a*m^k = a*(p1^k1*p2^k2*...*pn^kn)^k = a*(p1^k1k*p2^k2k*...*pn^knk) = a*(p^d1*p2^d2*...*pn^dn)   我們要求的 k = min(p1,p2,...,pn)
AC代碼:
#include <map>
#include <set>
#include <stack>
#include <cmath>
#include <queue>
#include <cstdio>
#include <vector>
#include <string>
#include <bitset>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <algorithm>
#define ls (r<<1)
#define rs (r<<1|1)
#define debug(a) cout << #a << " " << a << endl
using namespace std;
typedef long long ll;
const ll maxn = 1e6+10;
const double eps = 1e-8;
const ll mod = 1e9 + 7;
const int inf = 0x3f3f3f3f;
const double pi = acos(-1.0);
ll f[100]={-1,1,0,0,2,10,4,40,92,352,724,2680,14200,73712,365596};
ll prime[] = {0, 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97};
ll getcnt( ll p, ll x ) {
    ll res = 0;
    while(x) {
        res += x/p;
        x /= p;
    }
    return res;
}
int main() {
    ios::sync_with_stdio(0);
    ll a[105];
    a[1] = 1, a[2] = 1;
    for( ll i = 3; i <= 92; i ++ ) {
        a[i] = a[i-1] + a[i-2];
    }
    ll x, m;
    cin >> x >> m;
    bool flag = false;
    for( ll i = 1; i <= 92; i ++ ) {
        if( a[i] == x ) {
            flag = true;
            break;
        }
    }
    if( flag ) {
        map<ll,ll> mp;
        vector<pair<ll,ll> > e;
        for( ll i = 1; i <= 25; i ++ ) {
            while(m%prime[i]==0) {  //m中有多個相同的質數
                mp[prime[i]] ++;
                m /= prime[i];
            }
        }
        for( auto i : mp ) {
            e.push_back(make_pair(i.second,getcnt(i.first,x)));
        }
        ll k = 1e18+1;
        for( ll i = 0; i < e.size(); i ++ ) {
            k = min(k,e[i].second/e[i].first);  //因為質數可能有多個,所以求的質數還要除以質數的個數
        }
        cout << k << endl;
    } else {
        cout << f[x%min((ll)13,m+1)+1] << endl;
    }
    return 0;
}

  

牛客小白月賽6 水題 求n!在m進制下末尾0的個數 數論