1. 程式人生 > >騰訊2019校招研發卷

騰訊2019校招研發卷

第一題

給出n,求最小的正整數m 使得LCM(1...n)==LCM(n+1...m)

/**
 * 給出n  求最小的正整數m 使得LCM(1...n)==LCM(n+1...m)
 * 推結論的題 直接是求小於等於n的素數次方數*2
 */
#include <iostream>
using namespace std;
const int MAXN = 1e6+5;
long long p[MAXN];
bool prime[MAXN];
int k;
void init()
{
    k = 0;
    memset(prime, 0, sizeof(prime));
    prime[0] = prime[1] = 1;
    for(auto i=2; i<MAXN; i++)
    {
        if(!prime[i])
        {
            p[k++] = i;
            for(long long j=i*i; j<MAXN; j+=i)
                prime[j] = 1;
        }
    }
}
int main()
{
    init();
    int n;
    while(cin>>n)
    {

        int res = 2;
        for(auto i=2; i<=n; i++)
        {
            if(!prime[i])
            {
                int sum = i;
                while(sum <= n/i)
                    sum *= i;
                res = max(res, (n/sum+1)*sum);
            }
        }
        cout<<res<<endl;
    }
    return 0;
}

第二題

單向有環圖,求滿足要求的點(該點可達頂點數<可達該點的頂點數)的個數。用圖的深度遍歷可解。

考試的時候地點沒選好,吵吵鬧鬧的,心態爆炸,竟然把標記已訪問節點的陣列給去掉了,遇到有環的case就把棧給爆了。

#include<iostream>
#include <vector>
#include <unordered_set>
using namespace std;
void Dfs(const vector<unordered_set<int>>& path,vector<int>& visited,unordered_set<int> & canVisit,int cur)
{
    for(auto i=path[cur].begin();i!=path[cur].end();++i)
    {
        if(visited[*i]==0) {
            visited[*i]=1;
            canVisit.insert(*i);
            Dfs(path, visited, canVisit, *i);
        }
    }
    return ;
}
int main()
{
    int n,m,u,v;
    while(cin>>n>>m) {
        vector<unordered_set<int>> path(n);
        vector<unordered_set<int>> canVisit(n);
        for(auto i=0;i<m;++i){
            cin>>u>>v;
            u-=1;
            v-=1;
            path[u].insert(v);
        }
        vector<int> beVisted(n,0);
        for(auto i=0;i<n;++i){
            vector<int> visited(n,0);
            Dfs(path,visited,canVisit[i],i);
        }
        for(auto i=0;i<n;++i){
            for(auto j:canVisit[i]){
                ++beVisted[j];
            }

        }
        int cnt=0;
        for(auto i=0;i<n;++i){
            if(beVisted[i]>canVisit[i].size())
                cnt++;
        }
        cout<<cnt<<endl;
    }
}

第三題

輸入三個數A、B、C。輸出是否存在A的倍數d滿足d%B==C。存在輸出"YES",不存在輸出"NO"。

把這道題目想複雜了,覺得case肯定會有很大的數,所以沒有用暴力列舉做,放棄了這道題。這道題神奇的地方是結果是根據case來的。題中並沒有說明A、B、C的範圍,但經過網友們的實測,case的範圍有限,因此絕大部分人都用暴力列舉來通過。但這些解法在輸入較大的CASE總歸是存在問題的。下面是暴力列舉的解法。

#include <iostream>
using namespace std; 
int main() {
    int n; 
    int a, b, c; 
    while(cin >> n){ 
        for(auto i=0;i<n;++i) {
            cin >> a >> b >> c; 
            int m = a - b; 
            bool r=false; 
            for(int x = 0; x < 1000; x++) {
                for(int y = -1000; y < 1000; y++) {
                    if(x * m + y * a == c) { 
                        r = true; 
                        break; 
                    }  
                } 
            }
            cout << (r ? "YES" : "NO") << endl; 
        }
    }
    return 0;  
}

題目都比較基礎,為了省事在二餐西餐廳考的(一直聽說二餐西餐廳是個閱讀思考的好地方,結果被現實狠狠扇了一巴掌),結果到了11點好多人來吃飯,熙熙攘攘,又加上對第三題判斷失誤,覺得沒法用列舉解決,心態爆炸,本來能AC的題都沒AC。感覺跟心心念的鵝廠無緣了,涼涼...