大数分解质因数:Mark the Rope

Mark the Rope

Time Limit: 20000/10000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 245    Accepted Submission(s): 73


Problem Description
Eric has a long rope whose length is N, now he wants to mark on the rope with different colors. The way he marks the rope is:
1. He will choose a color that hasn’t been used
2. He will choose a length L (N>L>1) and he defines the mark’s value equals L
3. From the head of the rope, after every L length, he marks on the rope (you can assume the mark’s length is 0 )
4. When he chooses the length L in step 2, he has made sure that if he marks with this length, the last mark will be at the tail of the rope
Eric is a curious boy, he want to choose K kinds of marks. Every two of the marks’ value are coprime(gcd(l1,l2)=1). Now Eric wants to know the max K. After he chooses the max K kinds of marks, he wants to know the max sum of these K kinds of marks’ values.
You can assume that Eric always can find at least one kind of length to mark on the rope.
 

Input
First line: a positive number T (T<=500) representing the number of test cases
2 to T+1 lines: every line has only a positive number N (N<2 63) representing the length of rope
 

Output
For every test case, you only need to output K and S separated with a space
 

Sample Input
   
   
   
   
2 180 198
 

Sample Output
   
   
   
   
3 18 3 22
 

Source
2012 Multi-University Training Contest 5

这题看第一眼感觉题目好麻烦不想看,耐着性子看完发现思路比较简单,除了数据有点大以外 = =
不过这题过了很久都没人尝试,到最后好像也只有三四十个提交,过的就更少了,
我有点怀疑我的算法,但想来想去确实应该这样做,说白了就是把一个数n分解质因数,比如有a, b, c三个质因数
再比如n = a^i * b^j * c^k,于是结果就是a^i + b^j + c^k
思路很简单,但有个bug就是2^63-1这样级别的数你该打多少的素数表?事实证明就算时间够你的数组也会超,编译都通不过
这是就要用到两个函数miller_rabin, 和pollard_rho,大概就是伪随机素数的原理
具体的做法是
1)先打10^6次方级别的素数表,完了用n一个一个去除,最后剩的最大也只可能是个10^12级别左右的数,
2)再用miller_rabin判断剩下的n是不是质数,是的话直接就结了
2)如果不是的话就用pollar_rho,得它的一个质因子,很容易证明会是一个10^6级别左右的数,然后再除一次得另一个10^6级别左右的质因数,然后就完了
需要注意的特判是: 如果n光由一个质因子组成,比如n = a^i,那么ans = a^(i-1),因为题目规定能取的L < n

/******/中间的神奇函数来自c_cloud 的代码

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cmath>
#include <cstdlib>

using namespace std;

#define sq(x) (x)*(x)
#define LL long long
//const long long maxn =  2007483647;
const long long maxn =    4000005;
int cnt;
bool isp[maxn];
long long prime[2000000];

void init() {
	for(int i = 0; i < maxn; i++) {
        isp[i] = true;
	}
	isp[0] = isp[1] = false;
	cnt = 0;
	for(int i = 2; i < maxn; ++i) {
        if(cnt >= 50000001){
        printf("MLE");
        break;
        }
        if(isp[i]) prime[cnt++] = (LL)(i);
		for(int j = 0; j < cnt && prime[j] * i < maxn; ++j) {
		    isp[prime[j] * i] = false;
			if (i % prime[j] == 0) // 这句break是将复杂度降到线性的关键
				break;
		}
	}
}

/****************************************************************/

long long mult_mod(long long x, long long y, long long n)
{
    long long t, T, a, b, c, d, e, f, g, h, v, ans;
    T = (long long)(sqrt(double(n) + 0.5));
    t = T * T - n;
    a = x / T;
    b = x % T;
    c = y / T;
    d = y % T;
    e = a * c / T;
    f = a * c % T;
    v = ((a * d + b * c) % n + e * t) % n;
    g = v / T;
    h = v % T;
    ans = (((f + g) * t % n + b * d) % n + h * T) % n;
    while(ans < 0) ans += n;
    return ans;
}
long long fun(long long m, long long n)
{
    long long a, ans = 1;
    rand();
    a = rand();
    a *= rand() % (n - 1);
    a *= rand() % (n - 1);
    a = a % (n - 1) + 1;
    while(m)
    {
        if(m & 1) ans = mult_mod(ans, a, n);
        m >>= 1;
        a = mult_mod(a, a, n);
    }
    return ans;
}
long long gcd(long long a, long long b)
{
    if (b == 0) return a;
    else return gcd(b, a % b);
}
long long f(long long x, long long n)
{
    return (mult_mod(x, x, n) + 1) % n;
}

//判断一个数是不是质数
int miller_rabin(long long n)
{
    if(n == 2) return 1;
    if(n < 2 || (n & 1) == 0) return 0;
    long long m = n - 1, s = 0, a, i, j;
    while(!(m & 1))
    {
        m >>= 1;
        s++;
    }
    for(i = 1; i <= 10; i++)
    {
        a = fun(m, n);
        if(a == 1) continue;
        for(j = 1; j <= s; j++)
        {
            if(a == n - 1) break;
            a = mult_mod(a, a, n);
        }
        if(j > s) return 0;
    }
    return 1;
}

//获得n的一个质因子,但n必须是合数
long long pollard_rho(long long n)
{
    if (n < 2) return 0;
    if (!(n & 1)) return 2;
    long long x, y, i, d;
    for(i = 1; i <= 10; i++)
    {
        rand();
        x = rand() % n;
        y = f(x, n);
        d = gcd((y - x + n) % n, n);
        while(d == 1)
        {
            x = f(x, n);
            y = f(f(y, n), n);
            d = gcd((y - x + n) % n, n) % n;
        }
        if(d) return d;
    }
    return 0;
}

/**************************************************/

long long n;
long long tt;

int main(){
    int t;
    int i;
    int pp;
    init();
    scanf("%d", &t);
    while(t --){
        scanf("%I64d", &n);
        long long sqn = (long long)sqrt((double)n) + 1;
        int count = 0;
        long long ans = 0;
        for(i = 0; prime[i] <= sqn && i < maxn && prime[i]; i ++){
            if(n % prime[i] == 0){
                count ++;
                tt = prime[i];
                while(1){
                    if(n % (tt * prime[i]) == 0)
                        tt *= prime[i];
                    else
                        break;
                }
                n /= tt;
                //printf("tt= %I64d\n",tt);
                ans += tt;
                pp = prime[i];
            }
        }
        if(count == 1 && n == 1)
            ans /= pp;
        if(n != 1){
            if(miller_rabin(n)){
                if(count != 0){
                    ans += n;
                    count ++;
                }
            }
            else{
                long long xx = pollard_rho(n);
                if(xx == n/xx){
                    ans += xx + n/xx;
                    count ++;
                }
                else{
                    ans += xx + n/xx;
                    count += 2;
                }
            }
        }
        printf("%d %I64d\n", count, ans);
    }
    return 0;
}













你可能感兴趣的:(c,equals,input,fun,output,Training)