牛客 小y的质因数 (数学,数据范围,数量级)

https://ac.nowcoder.com/acm/contest/30880/E

  • \(nump >= logx - k, x<=1e12,k <=10\) logx 约为39,范围内对于一个数最多只用看是否存在大于等于39个质因子。
  • 为了找出最大的那个质因子,让x取10e12,k取10,有29个质因子,让其中28个都为2,得到最大质因子为1012/228 = 3725,让质因子上线设为4 * 10^3. 小于等于4000的质数有550个。
  • 我们dfs将质因子组合出所有可能符合条件的x,每个质数可能使用0-40次,就是40 * 550 时间复杂度不过2e4. 将可能的x存到vector里
  • 对于询问,在vector里面二分就好了。
#include<bits/stdc++.h>
using namespace std;
#define IOS ios::sync_with_stdio(false) ,cin.tie(0), cout.tie(0);
//#pragma GCC optimize(3,"Ofast","inline")
typedef long long ll;
const int N = 2e5 + 5;
const int M = 1e6 + 5;
const ll LNF = 0x3f3f3f3f3f3f3f3f;
const int mod = 1e9 + 7;
vector<int> fac; int cnt; bool st[5000];
vector<ll> num[11];
inline int Log2(ll x){
        double X = x;
        if ( X == 1 ) return 0;
        return ((* (unsigned ll*) &X >> 52) & 1023) + 1 + !(x == (x & (-x)));
}
void Sieve() {
    int n = 4000; st[0] = st[1] = 1;
    for(int i = 2; i <= 4000; ++ i) {
        if(!st[i]) fac.push_back(i);
        for(int j = 0; j < fac.size() && fac[j] * i <= n; ++ j) {
            st[i * fac[j]] = 1; 
            if(i % fac[j] == 0) break;
        }
    }
}
void solve () {
    ll l, r, k; cin >> l >> r >> k;
    int ans= 0 ;
    for(int i = 0; i <= k; ++ i) {
        ans +=  upper_bound(num[i].begin(), num[i].end(), r) - lower_bound(num[i].begin(), num[i].end(), l);
    }
    cout << ans << endl;
}

void dfs ( int pos, ll x, int nump ) {
    if(Log2(x) - nump > 10) return;
    if(pos == fac.size()) {
        num[Log2(x) - nump].push_back(x);
        return;
    }
    for (int i = 0; x <= 1e12; x *= fac[pos], ++ i) {
        dfs(pos + 1, x, nump + i);
    }
}
int main () {

    Sieve();
    dfs(0, 1, 0);
    for ( int i = 0; i <= 10; i ++ ) sort ( num[i].begin(), num[i].end() );
    int t; cin >> t;
    while( t -- ) solve();
    return 0;
}
posted @ 2022-03-25 20:04  qingyanng  阅读(48)  评论(0编辑  收藏  举报