K题我用了Pollard_rho他也过不了啊

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define inf 1e18
#define pll pair<ll, ll>
#define vi vector<int>
#define vl vector<ll>
#define fi first
#define se second
#define lll __int128

ll an[] = {2, 3, 5, 7, 11, 13, 17, 61};
map<ll, ll> mp;//存因数和对应出现次数
int num = 0;
ll Random(ll n)//生成0到n之间的整数
{
    return (double) rand() / RAND_MAX * n + 0.5;//(doubel)rand()/RAND_MAX生成0-1之间的浮点数
}
ll q_mul(ll a, ll b, ll p)//大数模
{
    ll sum = 0;
    while (b) {
        if (b & 1)//如果b的二进制末尾是零
        {
            (sum += a) %= p;//a要加上取余
        }
        (a <<= 1) %= p;//不断把a乘2相当于提高位数
        b >>= 1;//把b右移
    }
    return sum;
}
ll q_mod(ll a, ll n, ll p)//快速幂
{
    a = a % p;
    //首先降a的规模
    ll sum = 1;//记录结果
    while (n) {
        if (n & 1) {
            sum = q_mul(sum, a, p);//n为奇数时单独拿出来乘
        }
        a = q_mul(a, a, p);//合并a降n的规模
        n /= 2;
    }
    return sum;
}
//Miller-Rabin
bool witness(ll a, ll n) {
    ll d = n - 1;
    ll r = 0;
    while (d % 2 == 0) {
        d /= 2;
        r++;
    }//n-1分解成d*2^r,d为奇数
    ll x = q_mod(a, d, n);
    //cout << "d " << d << " r " << r << " x " << x << endl;
    if (x == 1 || x == n - 1)//最终的余数是1或n-1则可能是素数
    {
        return true;
    }
    while (r--) {
        x = q_mul(x, x, n);
        if (x == n - 1)//考虑开始在不断地往下余的过程
        {
            return true;//中间如果有一个余数是n-1说明中断了此过程,则可能是素数
        }
    }
    return false;//否则如果中间没有中断但最后是余数又不是n-1和1说明一定不是素数
}
bool miller_rabin(ll n) {
    const int times = 10;//试验次数
    if (n == 2) {
        return true;
    }
    if (n < 2 || n % 2 == 0) {
        return false;
    }
    for (int i = 0; i < times; i++) {
        ll a = Random(n - 2) + 1;//1到(n-1)
        //cout << a << endl;
        if (!witness(a, n)) {
            return false;
        }
    }
    return true;
}
//求gcd
ll gcd(ll a, ll b) {
    return b == 0 ? a : gcd(b, a % b);
}
//Pollard-rho
ll Pollard_rho(ll n, ll c) {
    //cout << "n "  << n << " c " << c << endl;
    ll i = 1, k = 2;
    ll x = Random(n - 1) + 1;
    ll y = x;
    while (true) {
        i++;
        x = (q_mul(x, x, n) + c) % n;
        ll d = gcd(y - x, n);
        if (1 < d && d < n) {
            return d;
        }
        if (x == y) {
            return n;
        }
        if (i == k) {
            y = x;
            k <<= 1;
        }
    }
}
void find(ll n, ll c) {
    if (n == 1)//找完了
    {
        return;
    }
    if (miller_rabin(n))//找到了质数
    {
        num++;
        mp[n]++;
        return;
    }
    ll p = n;
    while (p >= n)//找p的因数
    {
        p = Pollard_rho(p, c--);//返回p的因数或1或本身
    }
    find(p, c);//递归地找p的因子
    find(n / p, c);
}
void jie(ll x){
    num = 0;
    mp.clear();
    find(x, 2137342);//随机选取的c
    if (mp.empty())
        mp[x]++;
}

void solve() {
	ll n;
	cin >> n;
	set<ll> st;
	for(ll i = 1; i <= n; i++){
		ll x;
		cin >> x;
		jie(x);
		ll y = 1;
		for(pll p : mp){
			ll z = p.fi, c = p.se;
			if(c & 1)
				y *= (z);
		}
		st.insert(y);
	}
	cout << st.size() << endl;
}

int main() {
	ios::sync_with_stdio(false);
  	cin.tie(0);
  	cout.tie(0);
	solve();
	return 0;
}


全部评论
你Pollard写法带一个log,建议用我那个板子,感觉优化到不能再优化了。 https://ac.nowcoder.com/acm/contest/view-submission?submissionId=66674552 分解1e6以下是log复杂度,以上是n^(1/4)。
1 回复 分享
发布于 2024-01-24 06:41 陕西

相关推荐

05-14 20:34
门头沟学院 Java
窝补药贝八股:管他们,乱说,反正又不去,直接说680
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客企业服务