SCAU 10674 等差对

10674 等差对

时间限制:1000MS  内存限制:65535K 提交次数:0 通过次数:0

题型: 编程题   语言: 无限制

Description

   今天是一个特别的日子,百年一遇的光棍节,2011.11.11,xym收到一个装着礼物的信封,是一位mm的XX书,里面是两个棒棒糖和一封信。
信里是一道智力题:
    定义如果<x0,y0>和<x1,y1>满足x0-x1=y0-y1,则称这两个为等差对。
mm的问题是,问在<x,y>(0<=x,y<=n)<0,0>,<0,1>…<1,0>,<1,1>…<2,0>,
<2,1>…<n,0>…<n,1>…这(n+1)^2个有序对中存在多少个等差对?
    但是xym因为昨晚听他们班的女生唱歌太晚睡觉了,严重影响状态,现在他只能请求各位scau未来的希望帮助他解决这个问题。

Input

第一行输入一个整数T(T<=1000),表示case数。
下面T行有T个case,每个case只有一个整数n(1<=n<=10^9),表示0<=x,y<=n;但是由于测试的时候发现用scanf("%lld",&n)有bug,所以为了修正这个bug,请各位用long long读入的同学在读入前先赋0给变量,
例如 long long n=0; scanf("%lld",&n);

Output

每个case输出一行,表示等差对的数量,这个结果可能很大,只需最后结果%20111111即可。

Sample Input

2
2
100

Sample Output

5
338350

Hint

注意不要让数据溢出,及时取模的处理

Source

by 201030720425

Provider

admin

 

#include<stdio.h>
int main()
{
    long long n = 0, res = 0;
    long long a, b, c;
    int  T;
    scanf("%d", &T);
    while(T--)
    {
        res = 0;
        n = 0;
        scanf("%lld", &n);
        
        a = n, b = n + 1, c = 2 * n + 1;             
            if (a%2 == 0) a /= 2;              
            else b/=2;                        
            if (a%3 == 0) a /= 3;            
            else if (b%3 == 0) b /= 3;        
            else c /= 3;                     
    
        res = (((a*b)%20111111*c)%20111111 - ((n+2)*(n-1))/2 - 1)%20111111;
        res = (res + ((n+1)*n)/2)%20111111;
        printf("%lld\n", res%20111111);
    }
    return 0;
}

解题思路:

Xo – Yo  = X1 – Y1  ->   Xo + Y1  =  X1 + Yo   即 : X0 + Y0 = X1 + Y1;

所以可以转化成函数的形式 F = X + Y;

输入一个数n ,(1<=n <= 10^9)

令  n = X+Y;    比如我取 n = 5  则用坐标表示即为图中红色的线, X , Y 的取值有0,1,

2, 3, 4 , 5

线上共有6个点, 可以有C 6 取 2, 得到 6*5/2 = 15种可能

同理,

在 5 = X+Y 上有          C 5 取 2, 得到 5*4/2 = 10 种可能

在 4 = X+Y 上有          C4 取 2, 得到 4*3/2 =  6 种可能

……

……

累加有 (5*4 + 4*3 + 3*2 + 2*1)/2   +  6*5/2

可以看到 以 6 =X+Y 为界限,上下方相同, 所以最终累加有:

(5*4 + 4*3 + 3*2 + 2*1)/2 *2   +  6*5/2 

(因为形成的都是正方形,所以没有上下不相等的可能)

可以推出公式为: (输入n)

n*(n-1) + (n-1)*(n-2) + …… + 2*1  + (n+1)*n/2  =

n^2 – n + (n-1)^2 – (n-1) + …… + 2^2 – 2

因为: 1^2 + 2^2 + 3^2 + 4^2 + …… + n^2  = n*(n+1)*(2n+1)/6

       2+3+4+5+ …… +n = (n+2)*(n-1)/2

由此得出代码中的式子……

//至于这里为什么能这样写,我的理解是: a和b中有一个是偶数,理所当然其一能被2整除
//如果a,b不能被3整除,那么应该能够知道 三个连续的正整数中一定有一个能被3整除,
//对于n(>=2)来说,n和n+1不能被3整除,那么n-1和n+1一定能被3整除,
//而2*n+1 = n-1 + n+1, 所以a,b,c中一定有一个数能被3整除!
//这也许就是n*(n+1)*(2n+1)%6 == 0 屹立不倒的原因吧。

残余问题:

公式的使用:(a*b)%c = ((a%c)*(b%c))%c

运算规则:   

模运算与基本四则运算有些相似,但是除法例外。其规则如下:   

(a + b) % p = (a % p + b % p) % p (1)   

(a - b) % p = (a % p - b % p) % p (2)   

(a * b) % p = (a % p * b % p) % p (3)   

ab % p = ((a % p)b) % p          

(4)   

结合律:

((a+b) % p + c) % p = (a + (b+c) % p) % p (5)   

((a*b) % p * c)% p = (a * (b*c) % p) % p  (6)    

交换律:

(a + b) % p = (b+a) % p   (7)   

(a * b) % p = (b * a) % p (8)   

分配律:

((a +b)% p * c) % p = ((a * c) % p + (b * c) % p) % p (9)

原文地址:https://www.cnblogs.com/liaoguifa/p/2781724.html