zgg的课时作业

Description

对任意正整数$n$,$f(n)$为满足$|x^2-y^2|=n$的有序整数对$(x,y)$的个数。

现在给出$m$个正整数$a_1,a_2,\cdots,a_m$

令$sum=f(a_1)+f(a_2)+\cdots +f(a_m)-m$(保证$sum\gt 1$)

若$sum$为合数,求出在$[1,sum]$区间内所有满足以下条件的合数$x$的个数:

$$x|(2^x-1)$$

若$sum$为质数,求出在$[1,sum^2]$区间内所有满足以下条件的整数x的个数:

$$sum|(2^x-1)$$

Input Format

第一行给出了正整数$m$

接下来$m$行为$m$个正整数$a_1,a_2,\cdots ,a_m$

Output Format

第一行输出$sum$。

第二行输出满足条件的$x$的个数。

Sample Input

1
4

Sample Output

3
4

Hint

$(x,y)=(2,0),(-2,0),(0,2),(0,-2)$

故$sum=4-1=3$

$3$为质数

满足条件的$x$分别为:$2,4,6,8$,共$4$个

【数据规模与约定】

$40\%$:$m\le 1000$

$40\%$:$sum$为合数

$100\%$:$m\le 10^4,a_i\le 10^{10}$

 

解题报告

$f(x)$的值

 

根据题意,$f(n)$为满足$|x^2-y^2|=n$的有序数对$(x,y)$的个数。

 

将式子稍微转变一下,变成$|(x+y)(x-y)|=n$,所以设$a=|x+y|$,$b=|x-y|$。所以我们用$[a,b]$来代替$(x,y)$,则$[a,b]$需要满足$a \cdot b = n$,且$a$、$b$的奇偶性相同。

 

当$x、y \neq 0$时,由$(x,y)$衍生出的$(x,y)$、$(x,-y)$、$(-x,y)$、$(-x,-y)$、$(y,x)$、$(y,-x)$、$(-y,x)$、$(-y,-x)$,都是满足题意的,将它们写成$[a,b]$形式,只能写出两个,即$[a,b]$、$[b,a]$。

 

当$x=0$或$y=0$时,在$(x,0)$与$(0,y)$中,必然有$x=y$,所以由$(x,y)$可以衍生出$(0,x)$、$(x,0)$、$(0,-x)$、$(-x,0)$,而写成$[a,b]$的形式只能写出一个。

 

综上所述,存在满足条件的$(x,y)$序对的个数为$[a,b]$序对个数的$4$倍。

 

对$n$的取值进行分类讨论,当$n$为奇数时,$n$只能被拆分乘两个奇数的乘积。设$n = \prod_{i=1}^k P_i^{t_i}$($P_i$为互不相等的奇质数),则通过乘法原理易得将$n$拆分成两个奇数的乘积的方案数为$\prod_{i=1}^k (t_i+1)$。

 

当$n$为偶数时,$n$只能被拆分成两个偶数的乘积。设$n = 2^a \cdot \prod_{i=1}^k P_i^{t_i}$,则得到将$n$拆分成两个偶数的乘积的方案数为$(a - 1) \cdot \prod_{i=1}^k (t_i+1)$。

 

最后将结果乘以$4$即可。

 

$Sum$为合数

 

当$Sum$为合数时,要求求出区间$[1,Sum]$内满足$x|(2^x-1)$的合数$x$的个数。

 

若$x$为偶数,由于$2^x-1$必为奇数,则不存在$x$满足$x|(2^x-1)$。

 

若$x$为奇数,则假设$x|(2^x-1)$。这个式子等价于:$2^x \equiv 1\pmod{x}$。

 

假设已经找出一个最小的$r$满足:$2^r \equiv 1\pmod{x}$,则必然满足$r|x$。

 

设$P$为$x$的一个质因子,则必然有$2^r \equiv 1\pmod{P}$。且$2^{P-1} \equiv 1\pmod{P}$,由此可得$r|(P-1)$。

 

当$P$为$x$的最小质因子时(由于$x$为奇数,所以$P \gt 2$),若存在$r$满足$r|(P-1)$,则$P$不为$x$的最小质因子,矛盾。所以不存在奇合数$x$满足$x|(2^x-1)$。

 

综上所述,当Sum为合数是,区间$[1,Sum]$内满足$x|(2^x-1)$的合数$x$的个数为0。

 

$Sum$为质数

 

当$Sum$为质数时,要求求出区间$[1,sum^2]$内满足$Sum|(2^x-1)$的整数$x$的个数。

 

同样的,这个式子等价于:$2^x \equiv 1\pmod{Sum}$。

 

找出一个最小的$r$满足:$2^r \equiv 1\pmod{Sum}$,则必然满足$r|x$。即任何一个满足条件的$x$都是$r$的倍数。

 

因为$2^r\equiv1\pmod{Sum}$,所以$2^{kr}=(2^r)^k\equiv1^k=1\pmod{Sum}$。($k\in Z$)。即所以任何一个$r$的倍数都满足条件。

 

综上所述,在区间$[1,Sum^2]$内满足条件的$x$的个数即在该区间内$r$的倍数的个数。

 

代码:

#include <cstdio>

int m, f[100010], p[10000], pn;
long long a, sum;

long long F(long long x)
{
    long long ret = 1, t = 0;
    if (x % 4 == 2) return 0;
    if (x % 4 == 0) x /= 4;
    for (int i = 0, j, k; i < pn && x > 1; i++)
    {
        j = p[i];
        k = 1;
        while (x % j == 0)
        {
            k++;
            x /= j;
        }
        ret *= k;
    }
    if (x != 1) ret *= 2;
    return ret;
}

bool isPrime(long long x)
{
    if (x < 100000)
    {
        return f[x] == 0;
    }
    for (int i = 0; i < pn; i++)
    {
        if (x % p[i] == 0)
        {
            return false;
        }
    }
    return true;
}

long long pow(long long x, long long p, long long mod)
{
    if (p == 0) return 1;
    if (p == 1) return x % mod;
    if (p == 2) return x * x % mod;
    return pow(pow(x, p / 2, mod), 2, mod) * pow(x, p % 2, mod) % mod;
}

long long Find_r(long long x)
{
    long long ret = -1;
    x--;
    for (long long i = 2; i * i <= x; i++)
    {
        if (x % i) continue;
        if (pow(2, i, x + 1) == 1) return i;
        if (pow(2, x / i, x + 1) == 1)
        {
            if (ret == -1 || x / i < ret)
            {
                ret = x / i;
            }
        }
    }
    return ret;
}

int main()
{
    f[0] = f[1] = 1;
    for (int i = 2; i <= 100000; i++)
    {
        if (f[i] == 0)
        {
            for (int j = i + i; j <= 100000; j += i)
            {
                f[j] = i;
            }
            p[pn++] = i;
        }
    }
    scanf("%d", &m);
    for (int i = 0; i < m; i++)
    {
        scanf("%lld", &a);
        sum += F(a) * 4 - 1;
    }
    printf("%lld\n", sum);
    if (isPrime(sum))
    {
        long long r = Find_r(sum);
        if (r == -1) //找不到r时即r=phi(sum)=sum-1
        {
            r = sum - 1;
        }
        sum = sum * sum / r;
        printf("%lld", sum);
    }
    else
    {
        printf("0");
    }
}

 

posted @ 2015-06-24 19:45  Lightning34  阅读(149)  评论(0编辑  收藏  举报