2017北大校赛 J题 pairs

题目链接 http://poj.openjudge.cn/practice/C17J/

orz 原来是一道无脑枚举题目

只是很卡常数而已

复杂度算错也是很醉orz

当时怎么没想着优化常数呢

题解:枚举x,p,y,就可以了

当然,普通暴力枚举肯定会超时,复杂度是M^1.5

(一开始算的是M^1.5logM,实际上算错了,因为M + M/4 + M/9 + .... 不超过2*M)

我们考虑预处理一些部分,其实就是预处理出每个数i的小于sqrt(i)的所有约数

这个复杂度实际上是MlogM

之后我们再暴力枚举,枚举y的时候直接枚举约数,可以优化很大的常数

同时要感谢ljw神犇orz,指出了我复杂度计算上的错误

#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <vector>
#define pb push_back
using namespace std;
int T, M, ans;
int f[800000];
vector<int> V[800001];
int main(){
    cin>>T;
    for(int i = 1; i <= 800000; i++) V[i].pb(1);
    for(int i = 2; i <= sqrt(800000)+0.5; i++){
        for(int j = 1; j*i <= 800000; j++){
            V[j*i].pb(i);
        }
    }
    while(T--){
        ans = 0;
        cin>>M;
        int _ = sqrt(M) + 0.5;
        for(int x = 1; x <= _; x++){
            memset(f, 0, sizeof(f));
            for(int p = 1; p <= M/x/x; p++){
                int t = M - p*x*x; 
                if(t <= 0) break;
                for(int i = 0; i < V[t].size(); i++){
                    int y = V[t][i];
                    if(!f[y]) { f[y] = 1;  ans++; }
                    if(!f[t/y]) { f[t/y] = 1; ans++; }
                }
            }
        }
        cout<<ans<<endl;
    }
}
原文地址:https://www.cnblogs.com/Saurus/p/6916964.html