欧拉的全功能练习代码在线判断失败

时间:2018-03-02 08:31:46

标签: c++ number-theory

具体是UVA problem number 11327

  

给定一系列介于0和1之间的所有有理数(0 / 1,1 / 1,1 / 2,1 / 3,2 / 3,...,n / d)打印第k个分数< / p>

我已经使用了他们的调试器,我的程序会输出他们给出的完全相同的答案,但法官仍然认为它不正确。

我使用Euler's totient function找到分母并迭代通过等于1的GCD来找到分子。据我所知,这应该足够了。

任何帮助都将不胜感激。

#include <iostream>
#include <stdlib.h>
#include <vector>
#include <math.h>
using namespace std;

//Calculate the greatest common divisor of a and b
long long GCD(long long a, long long b){
    if (a == 0){
        return b;
    }
    return GCD(b%a, a);
}

int main(){
    long long input;
    vector <long long> inputVector;
    vector <long long> phiValues;
    long long totient;
    long long total;
    int numerator;
    int denominator;

    while(cin >> input){
        if(input == 0){
            break;
        }
        inputVector.push_back(input);
    }

    // Calculate phi for all integers from 1 to
    // 20000 and store them 
    for(int i = 1; i <= 200000; i++){
        long long current = i;
        totient = current;
        for(long long k = 2; k <= sqrt(i); k++){
            if(current % k == 0){
                totient -= totient / k;
                while(current % k == 0){
                    current /= k;
                }
            }
        }
        if(current > 1){
            totient -= totient / current;
        }
        phiValues.push_back(totient);
    }

    for(int i = 0; i < inputVector.size(); i++){
        long long N = inputVector[i];
        total = 1;
        for(int j = 0; j <= phiValues.size(); j++){
            if(total >= N){
                if(N == 1){ //For the case of N = 1
                    denominator = 1;
                }else{ 
                    denominator = j; 
                }
                total -= phiValues[j-1]; 
                break;
            }
            total += phiValues[j];

        }
        int index = 0;
        for(int j = 1; j <= denominator; j++){
            if(GCD(j, denominator) == 1){
                index++;
                if(index == N - total){
                    numerator = j;
                    break;
                }
            }
        }
        cout << numerator << '/' << denominator << endl;
    }
    return 0;
}

1 个答案:

答案 0 :(得分:0)

Here @jte表示可以在O(N*logN)中实现PHI的计算:

phi[0]  = phi[1] = 0;
for (int i=2; i<maxn; ++i)
    phi[i] = i - 1;
for (int i=1; i<maxn; ++i)
        for (int j=i+i; j<maxn; j+=i)
                 phi[j] -= phi[i];

我找不到你的代码问题。可能是TLE(超出时间限制)问题,因为你应该使用二分搜索来找到分母。但是这段代码将获得ACCEPTED:

#include<bits/stdc++.h>

using namespace std;

const int N = 200031;

int pr[N+31],phi[N+31];
vector<int> P[N+31];
long long S[N+31];

int count(int n,int X)
{
    int res=n;
    int N=P[X].size();
    for (int mask=1;mask<(1<<N);mask++) {
        int C=0;
        int prod=1;
        for (int j=0;j<N;j++)
            if (mask&(1<<j))
                C++,
                prod*=P[X][j];
        if (C%2)
            res-=n/prod;
        else
            res+=n/prod;
    }
    return res;
}

int solve(int need,int val)
{
    int l,r;
    l=1;
    r=val;
    while (l<r) {
        int mid=l+r;
        mid/=2;
        int Q=count(mid,val);
        if (Q>=need)
            r=mid;
        else
            l=mid+1;
    }
    return l;
}

int main()
{
    ios_base::sync_with_stdio(0);

    pr[1]=1;
    for (int i=1;i<=N;i++) {
        if (pr[i])
            continue;
        for (int j=i;j<=N;j+=i)
            P[j].push_back(i),
            pr[j]=1;
    }

    for (int i=1;i<=N;i++) {
        phi[i]=i;
        for (int j=0;j<P[i].size();j++) {
            int val=P[i][j];
            phi[i]=phi[i]/val*(val-1);
        }
    }
    for (int i=1;i<=N;i++)
        S[i]=S[i-1]+phi[i];

    long long x;
    while (cin>>x) {
        if (x==0)
            break;
        --x;
        if (x==0)
        {
            cout<<0<<"/"<<1<<endl;
            continue;
        }
        int id=lower_bound(S+1,S+N+1,x)-S;
        x-=S[id-1];
        int ps=solve(x,id);
        cout<<ps<<"/"<<id<<endl;
    }

    return 0;
}