zoukankan      html  css  js  c++  java
  • 神炎皇 解题报告

    神炎皇

    问题描述

    神炎皇乌利亚很喜欢数对, 他想找到神奇的数对。
    对于一个整数对((a,b)), 若满足 (a+ble n)(a+b)(ab) 的因子, 则称为神奇的数对。 请问这样的数对共有多少呢?

    输入格式

    一行一个整数 (n)

    输出格式

    一行一个整数表示答案, 保证不超过 (64) 位整数范围。

    数据范围与约定

    对于(20\%)的数据 (nle 1000)

    对于(40\%)的数据 (nle 100000)

    对于(60\%)的数据 (nle 10000000)

    对于(80\%)的数据 (nle 1000000000000)

    对于(100\%)的数据 (nle 100000000000000)


    说一下考试时候的打表历程吧(拿了(40pts),如果让我交答案表了就有(60pts)了)

    第一个表的枚举(a+b),然后暴力找(a,b)

    得到了一个没什么用的答案表

    把数对打出来

    研究一下发现每个(a+b)的贡献可以这么算,设(f(x))(x=a+b)的贡献

    (f(x)=sum_{i=1}^x[x|i^2])

    证明一下也不难,因为(gcd(i,x)=gcd(x-i.x))

    发现这样没什么卵用,继续打表发现

    后面的都是第一个的倍数,理解起来也非常简单,考虑每个数最小满足的数怎么搞。

    发现就是唯一分解以后,指数除(2)向上取整,拿原数除最小数即为个数(-1)(因为自己不算),则又有

    (x=prod p_i^{c_i})(f(x)=prod p_i^{lfloorfrac{c_i}{2} floor}-1)

    (g(x)=prod p_i^{lfloorfrac{c_i}{2} floor})

    发现(g(x))是积性函数,然而窝并没想到(O(n))的筛法,只好只拿了(40pts)


    正解:

    设有一对满足条件的数对((a,b))

    (d=gcd(a,b),a'=frac{a}{d},b'=frac{b}{d})

    则要满足条件((a'+b')d|a'b'd^2)

    ((a'+b')|a'b'd)

    因为((a',b')=1),所以((a'+b',a')=(a'+b',b')=1),所以((a'+b',a'b')=1)

    则条件为((a'+b')|d)

    (i=a'+b')(d=ki),那么有(id=i^2kle n)

    发现枚举(i)只需要到(sqrt n)就可以了,于是枚举(i)

    对于一个(i)(k)的取值个数为(lfloorfrac{n}{i^2} floor)

    考虑(i)内部的情况,发现是(varphi(i)),原因很简单,也是因为(gcd(i,x)=gcd(i,i-x)),考虑一下成对出现就可以了。

    那么答案就为(sum_{i=1}^{sqrt n}varphi(i)lfloorfrac{n}{i^2} floor)


    总结:

    1. 数据范围根号提示
    2. 想办法使用(varphi ,mu)什么的
    3. 胡乱更换枚举项试试(这是很多题的核心了,谁枚举的少好算,我就找谁)
    4. 不要忘记打个表

    Code:

    #include <cstdio>
    #define ll long long
    const int N=1e7;
    int pri[N+10],phi[N+10],ispri[N+10],cnt;
    ll ans,n;
    void init()
    {
        for(int i=2;i<=N;i++)
        {
            if(!ispri[i])
            {
                pri[++cnt]=i;
                phi[i]=i-1;
            }
            for(int j=1;j<=cnt&&pri[j]*i<=N;j++)
            {
                ispri[i*pri[j]]=1;
                if(i%pri[j]==0)
                {
                    phi[i*pri[j]]=phi[i]*pri[j];
                    break;
                }
                else
                    phi[i*pri[j]]=phi[i]*(pri[j]-1);
            }
        }
    }
    int main()
    {
        init();
        scanf("%lld",&n);
        for(ll i=1;i*i<=n;i++)
            ans=ans+phi[i]*(n/(i*i));
        printf("%lld
    ",ans);
        return 0;
    }
    

    2018.11.1

  • 相关阅读:
    [蓝桥杯] 第39级台阶
    [蓝桥杯] 马虎的算式
    POJ 1142 Smith Numbers(史密斯数)
    HDU 1181 变形课
    HDU 1728 逃离迷宫
    HDU 2188 悼念512汶川大地震遇难同胞――选拔志愿者 巴什博奕
    HDU 2177 取(2堆)石子游戏 (威佐夫博弈)
    HDU 1847 Good Luck in CET-4 Everybody! 博弈
    HDU 1525 Euclid's Game
    HDU 1517 A Multiplication Game 博弈
  • 原文地址:https://www.cnblogs.com/butterflydew/p/9889530.html
Copyright © 2011-2022 走看看