A 牛牛数三角形

原题链接

A 牛牛数三角形

题目大意

输入一个 n ( 1 ≤ n ≤ 1 0 18 ) n(1\le n\le 10^{18}) n(1n1018),代表一个三角形,他有 n ( 1 ≤ n ≤ 1 0 18 ) n(1\le n\le 10^{18}) n(1n1018)行,第一行有 n ( 1 ≤ n ≤ 1 0 18 ) n(1\le n\le 10^{18}) n(1n1018)个位置,第二行有 n − 1 n-1 n1个数……第 n n n行有1个位置,每一个位置对应一个数( 0 ∼ 9 0\sim 9 09中的一个数),从左上角数起,每 10 10 10个数为一循环。比如说如果 n = 70 n=70 n=70,那么这个三角形为:
0123456789012345678901234567890123456789012345678901234567890123456789
012345678901234567890123456789012345678901234567890123456789012345678
90123456789012345678901234567890123456789012345678901234567890123456
7890123456789012345678901234567890123456789012345678901234567890123
456789012345678901234567890123456789012345678901234567890123456789
01234567890123456789012345678901234567890123456789012345678901234
5678901234567890123456789012345678901234567890123456789012345678
901234567890123456789012345678901234567890123456789012345678901
23456789012345678901234567890123456789012345678901234567890123
4567890123456789012345678901234567890123456789012345678901234
567890123456789012345678901234567890123456789012345678901234
56789012345678901234567890123456789012345678901234567890123
4567890123456789012345678901234567890123456789012345678901
234567890123456789012345678901234567890123456789012345678
90123456789012345678901234567890123456789012345678901234
5678901234567890123456789012345678901234567890123456789
012345678901234567890123456789012345678901234567890123
45678901234567890123456789012345678901234567890123456
7890123456789012345678901234567890123456789012345678
901234567890123456789012345678901234567890123456789
01234567890123456789012345678901234567890123456789
0123456789012345678901234567890123456789012345678
901234567890123456789012345678901234567890123456
78901234567890123456789012345678901234567890123
4567890123456789012345678901234567890123456789
012345678901234567890123456789012345678901234
56789012345678901234567890123456789012345678
9012345678901234567890123456789012345678901
234567890123456789012345678901234567890123
45678901234567890123456789012345678901234
5678901234567890123456789012345678901234
567890123456789012345678901234567890123
45678901234567890123456789012345678901
2345678901234567890123456789012345678
901234567890123456789012345678901234
56789012345678901234567890123456789
0123456789012345678901234567890123
456789012345678901234567890123456
78901234567890123456789012345678
9012345678901234567890123456789
012345678901234567890123456789
01234567890123456789012345678
9012345678901234567890123456
789012345678901234567890123
45678901234567890123456789
0123456789012345678901234
567890123456789012345678
90123456789012345678901
2345678901234567890123
456789012345678901234
56789012345678901234
5678901234567890123
456789012345678901
23456789012345678
9012345678901234
567890123456789
01234567890123
4567890123456
789012345678
90123456789
0123456789
012345678
90123456
7890123
456789
01234
5678
901
23
4
接着,再输入一个 1 ≤ x ≤ n ≤ 1 0 18 1\le x\le n\le 10^{18} 1xn1018 1 ≤ y ≤ n − x + 1 ≤ n ≤ 1 0 18 1\le y\le n-x+1\le n\le 10^{18} 1ynx+1n1018 求出位置为第 x x x y y y列位置所对应的数(保证为 0 ∼ 9 0\sim 9 09)。

解题思路

考虑到 n ≤ 1 0 18 n\le 10^{18} n1018,所以如果暴力,将会愉快超时!这时候我们考虑数学算法。
众所周知,有一个东西叫做等差数列,仔细观察,我们可以发现,随着 y y y的取值,有两种情况。当 y = n − x + 1 y=n-x+1 y=nx+1时,当前的位置就是从左上角数起第 n − x + 1 n-x+1 nx+1一直加到 n n n个,当 y ≠ n − x + 1 y\ne n-x+1 y=nx+1时,当前的位置就是从左上角数起第 n − x + 2 n-x+2 nx+2一直加到 n n n再加上 y y y个于是,我们可以推出(设 a n s ans ans ( x , y ) (x,y) (x,y)从左上角数起,第 a n s ans ans个):
a n s ( x , y ) = { y = n − x + 1     ( n + n − x + 1 ) × x 2 y ≠ n − x + 1     ( n + n − x + 2 ) × ( x − 1 ) 2 + y ans_{(x,y)}=\left\{\begin{matrix}y=n-x+1\ \ \ \frac{(n+n-x+1)\times x}{2} \\y\ne n-x+1\ \ \ \frac{(n+n-x+2)\times (x-1)}{2}+y\end{matrix}\right. ans(x,y)={ y=nx+1   2(n+nx+1)×xy=nx+1   2(n+nx+2)×(x1)+y
由于是从0开始数起,而我们是从1算起,所以需要减一,再模10。
因为数据太水直接使用c++内置的计算也可以AC,但是,如果真的达到 n = 1 0 18 − 1 n=10^{18}-1 n=10181的话,在计算时,就会溢出。于是,我们参考快速幂的想法:
10 ∗ 19 = 19 + 19 + 19 + 19 + 19 + 19 + 19 + 19 + 19 + 19 = 2 3 ∗ 19 + 2 1 ∗ 19 10*19=19+19+19+19+19+19+19+19+19+19=2^3*19+2^1*19 1019=19+19+19+19+19+19+19+19+19+19=2319+2119
也就是将其中一个因数拆分成二进制,于是,在进行模运算时,便可以保证不会溢出,写法如下:

/*Mod=10*/
unsigned long long times(unsigned long long a,unsigned long long b)
{
    
    
    unsigned long long ans=0;
    a=a%Mod;
    while(b){
    
    
        if(b&1)
            ans=(ans+a)%Mod;//累加答案
        a=a*2;//每次多乘2
        b/=2;//下一位
    }
    return ans;
}

代码实现

#include<bits/stdc++.h>
using namespace std;
const unsigned long long Mod=10;
unsigned long long n,x,y;
unsigned long long times(unsigned long long a,unsigned long long b)
{
    
    
    unsigned long long ans=0;
    a=a%Mod;
    while(b){
    
    
        if(b&1)
            ans=(ans+a)%Mod;//累加答案
        a=a*2;//每次多乘2
        b/=2;//下一位
    }
    return ans;
}
int main()
{
    
    
    cin>>n>>x>>y;
//  cout<<times((n+n-x+1)/2,x)<<endl;
//  cout<<times(4,1)<<endl;
    if(x==1){
    
    
        cout<<(y-1)%Mod;
        return 0;
    }
    if(y!=n-x+1){
    
    //如果不是当前这行的最后一个
        x--;//完整的行数减去1
        if((n+n-x+1)%2==0){
    
    //防止出现精度损失,这个判断为(n+n-x+1)可以整除2
            unsigned long long ans=(times((n+n-x+1)/2,x)+y)%Mod;//比第一位后y,所以加上y
            if(ans==0)//因为是从1算起,所以需要向前推一位
                cout<<9;//零特殊处理
            else
                cout<<ans-1;
        }
        else{
    
    //防止出现精度损失,这个判断为x可以整除2
            unsigned long long ans=(times((n+n-x+1),x/2)+y)%Mod;//比第一位后y,所以加上y
            if(ans==0)//因为是从1算起,所以需要向前推一位
                cout<<9;//零特殊处理
            else
                cout<<ans-1;
        }
    }
    else//如果是当前这行的最后一个
        if((n+n-x+1)%2==0){
    
    //防止出现精度损失,这个判断为(n+n-x+1)可以整除2
            unsigned long long ans=times((n+n-x+1)/2,x);//因为是整行的,所以不需要加上y
            if(ans==0)//因为是从1算起,所以需要向前推一位
                cout<<9;//零特殊处理
            else
                cout<<ans-1;
        }
        else{
    
    //防止出现精度损失,这个判断为x可以整除2
            unsigned long long ans=times((n+n-x+1),x/2);//因为是整行的,所以不需要加上y
            if(ans==0)//因为是从1算起,所以需要向前推一位
                cout<<9;//零特殊处理
            else
                cout<<ans-1;
        }
}

样例1

输入

7803917 6501657 800542

输出

s

样例2

输入

1000000000000000000 1000000000000000000 1

输出

9

Guess you like

Origin blog.csdn.net/weixin_41247488/article/details/120768656