2017年山东省第八届ACM大学生程序设计竞赛 B Quadrat(sdut 3894) 打表找规律

Quadrat

Time Limit: 1000MS Memory Limit: 65536KB

Problem Description

It is well-known that for any n there are exactly four n-digit numbers (including ones with leading zeros) that are self-squares: the lastn digits of the square of such number are equal to the number itself. These four numbers are always suffixes of these four infinite sequences: 

...0000000000 
...0000000001 
...8212890625 
...1787109376 

For example, =87909376, which ends with 09376.

You are required to count the numbers that are almost self-squares: such that each of the lastn digits of their square is at most d away from the corresponding digit of the number itself. Note that we consider digits 0 and 9 to be adjacent, so for example digits that are at most 3 away from digit 8 are 5, 6, 7, 8, 9, 0 and 1. 

Input

The first line contains the number of test cases t,1≤t≤72. Each of the next t lines contains one test case: two numbersn(1≤n≤ 18) and d(0≤ d≤3). 

Output

For each test case, output the number of almost self-squares with length n and the (circular) distance in each digit from the square at mostd in a line by itself.

Example Input

2
5 0
2 1

Example Output

4
12

Hint

In the second case, number 12's almost self-squares are: 00, 01, 10, 11, 15, 25, 35, 66, 76, 86, 90, 91


    没想到这是一道打表找规律的题目...当时省赛看着没人做,这题连看都没看= =题意是说有T组数据,每组数据其中n为数字的位数,d为数字的最大差,问有几个数字符合要求。这个要求就是说将一个数平方,然后将这个平方数取原来位数的后几位,这几位数字每一位的差都要小于等于d。比如25,平方之后是625,舍去之后为25,距离是相同的,都为0。再比如21,21的平方为441,舍去后得到41,与21的差第一位为2,第二位为0,所以d为2。

    要注意这题是一个环,0到9的距离不是9而是1。

    接下来这个题就通过打表找规律了,打出n在[1,6],d在[0,3]范围的数就足够了(一开始没注意d的范围打到了5....),下面是打表程序:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<math.h>
using namespace std;

int main()
{
    int T;
    int n,d;
    long long i,j;
    /*scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d",&n,&d);*/
    for(n=1;n<=6;n++)
    {
        for(d=0;d<=5;d++)
        {
            long long m=1;
            for(i=1;i<=n;i++)
            {
                m*=10;
            }
            if(d==0)
            {
                cout<<4<<" ";
                continue;
            }
            else
            {
                int ans=0;
                for(i=0;i<m;i++)
                {
                    int flag=0;
                    long long t=i;
                    long long p=t%m*t%m;
                    for(j=1;j<=n;j++)
                    {
                        int dis=abs(t%10-p%10);
                        if(dis>5)
                            dis=10-dis;
                        if(dis>d)
                            flag=1;
                        t/=10;
                        p/=10;
                    }
                    if(!flag)
                    {
                        //cout<<i<<"!!"<<endl;
                        ans++;
                    }
                }
                cout<<ans<<" ";
            }
        }
        cout<<endl;
    }
    return 0;
}



    通过表格可以发现,第一行依次往下都是4,第二行依次乘3,第三行依次乘5,第四行依次乘7,然后初始化出来就行了。注意数据范围比较大,要用long long。

    下面AC代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
long long a[20][20];
long long b[5]={1,3,5,7};

int main()
{
    int T;
    int n,d;
    int i,j;
    scanf("%d",&T);
    memset(a,0,sizeof(a));
    a[1][0]=4;
    a[1][1]=4;
    a[1][2]=8;
    a[1][3]=8;
    for(i=2;i<=18;i++)
    {
        for(j=0;j<4;j++)
        {
            a[i][j]=a[i-1][j]*b[j];
        }
    }
    while(T--)
    {
        scanf("%d%d",&n,&d);
        cout<<a[n][d]<<endl;
    }
    return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值