(dfs) hdu 4394 Digital Square

题目链接:

http://acm.hdu.edu.cn/showproblem.php?pid=4394

题目意思:

给定一个N(0<=N<=10^9),求最小的M,使得M^2%10^x=N ( x=0,1,2,3... ).

解题思路:

搜索。

从低位往高位依次处理。

   abcde

* abcde

------------

N(...n3n2n1)

显然可以根据N的个位确定e的可能的情况,把e确定后,再根据2*d*e=n2,得出d的可能情况,再根据2*c*e+d*d=n3得出c的可能情况,依次往高位搜索,最后比较求出最小的即可。

代码:

//#include<CSpreadSheet.h>

#include<iostream>
#include<cmath>
#include<cstdio>
#include<sstream>
#include<cstdlib>
#include<string>
#include<string.h>
#include<cstring>
#include<algorithm>
#include<vector>
#include<map>
#include<set>
#include<stack>
#include<list>
#include<queue>
#include<ctime>
#include<bitset>
#define eps 1e-6
#define INF 0x3f3f3f3f
#define PI acos(-1.0)
#define ll __int64
#define LL long long
#define lson l,m,(rt<<1)
#define rson m+1,r,(rt<<1)|1
#define M 1000000007
//#pragma comment(linker, "/STACK:1024000000,1024000000")
using namespace std;

vector<int>myv[12]; //myv[i]平方的个位为i的数字集合
int n;
bool flag;
int ans[22],cnt;
int last[22];
vector<int>be[12][12];//be[i][j]表示乘积个位为i,一个乘数为j,另外一个乘数的集合

void init()
{
    myv[1].push_back(1);myv[1].push_back(9);
    myv[4].push_back(2),myv[4].push_back(8);
    myv[6].push_back(4),myv[6].push_back(6);

    myv[9].push_back(3),myv[9].push_back(7);
    myv[5].push_back(5);
    myv[0].push_back(0);

    for(int i=0;i<=9;i++) //预处理出所有的情况
        for(int j=0;j<=9;j++)
        {
            for(int k=0;k<=9;k++)
            {
                if(j*k%10==i)
                    be[i][j].push_back(k);
            }

        }

}

void  dfs(int cur,int ji,int num) //cur表示当前的数,ji表示从低位进位的量,num表示第几位(从低位开始计算)
{
    if(!cur) //结束了
    {
        cnt=num-1;
        if(flag)
        {
            bool iste=false;

            for(int i=num-1;i>=1;i--) //能否更新小点
            {
                if(ans[i]<last[i])
                {
                    iste=true;
                    break;
                }
                else if(ans[i]>last[i])
                    break;
            }
            if(iste)
                memcpy(last,ans,sizeof(ans));
            
        }
        else
            memcpy(last,ans,sizeof(ans));

        flag=true;
        return ;
    }

    int temp=ji,le,pos=cur%10;

    for(int i=2;i<num;i++) //计算该位的值
    {
        temp+=ans[i]*ans[num+1-i];
    }
    le=temp%10;
    if(pos<le)
        pos+=10;
    pos-=le;

    if(pos%2)
    {
        return ;
    }

    for(int j=0;j<be[pos][2].size();j++)
    {
        int pp=be[pos][2][j];

        for(int i=0;i<be[pp][ans[1]].size();i++)
        {
            ans[num]=be[pp][ans[1]][i];

            int tt=temp;
            tt+=ans[num]*ans[1]*2;
            dfs(cur/10,tt/10,num+1);
           // printf("cur:%d \n",cur);
            //system("pause");
            /*if(flag)
                return;*/
        }

    }




}
int main()
{
   //freopen("in.txt","r",stdin);
   /*freopen("out.txt","w",stdout);

   for(int i=1;i<=40;i++)
        printf("%d ",i*i);*/



   int t;
   init();

   scanf("%d",&t);
   while(t--)
   {
       flag=false;
       scanf("%d",&n);

       cnt=0;
       for(int i=0;i<myv[n%10].size();i++)
       {
           ans[1]=myv[n%10][i];
           dfs(n/10,ans[1]*ans[1]/10,2);
           /*if(flag)
                break;*/
       }

       if(flag)
       {
           int i=cnt;
           while(!last[i]&&i>1)
                i--;
           for(;i>=1;i--)
           {
                printf("%d",last[i]);

           }

           putchar('\n');
       }
       else
            printf("None\n");
   }
   return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值