Quadrat
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;
}