OpenJ_POJ C17J Pairs

来源:互联网 发布:TensorFlow pca 编辑:程序博客网 时间:2024/04/29 05:44

Problem

poj.openjudge.cn/practice/C17J?lang=en_US
vjudge.net/contest/194746#problem/J(密码:happytraining)

Meaning

给出一个正整数 M,求正整数对(x,y),使得存在正整数 p 和 q,满足:p×x2+q×y=M

Analysis

由于 x2 增长的比 y 快,考虑枚举 x2 和 p,然后移项,得:Mp×x2=q×y,这个式子可以理解成把 Mp×x2 拆成它的两个因子相乘,记它的因子数为 d,那么对于这个枚举的 x,有 d 个 y 可以满足式子(就是那 d 个因子)。
但是,不能直接把 d 加入到答案,因为对于同一个(x,y),可能会有不同的数对(p,q)和(p’,q’),使得 Mp×x2=q×yMp×x2=q×y 成立,这样就算重了。
注意到对于每一个枚举的 x,Mp×x2 的因子(可行的 y)的极限范围是 [ 0 , M ],所以可以先枚举 x,对每一个枚举的 x,维护一个 [ 0 , M ] 的 vis 数组,标记某个因子是否出现过,然后枚举 p,把每个 Mp×x2 的所有因子找出来,在数组中标记它们。枚举完 p 后,扫一边 vis 数组统计答案。
可以用类似素筛的方法预处理出 [ 1 , M ] 中每个数的因子有哪些。这样看来很暴力,但看那个预处理的表又好像并没有很多。

Code

#include <cmath>#include <cstdio>#include <cstring>#include <vector>using namespace std;const int M = 800000;vector<int> div[M+1];void biao(){    for(int d = 1; d <= M; ++d)        for(int n = d; n <= M; n += d)            div[n].push_back(d);}bool vis[M+1];int main(){    biao();    int T;    scanf("%d", &T);    while(T--)    {        int m;        scanf("%d", &m);        int ans = 0;        // 枚举 x^2        for(int x = 1, ex = sqrt(1.0 * m); x <= ex; ++x)        {            // 标记因子的出现            memset(vis, false, sizeof vis);            // 枚举 p            for(int p = 1, ep = m / x / x; p <= ep; ++p)            {                int n = m - p * x * x; // 移项后的式子左边                for(int i = 0; i < div[n].size(); ++i)                    if(!vis[div[n][i]]) // 该因子第一次出现                    {                        vis[div[n][i]] = true;                        ++ans;                    }            }        }        printf("%d\n", ans);    }    return 0;}
原创粉丝点击