Digital Square(hdu 数论 4394,bfs求后n位相同)

Digital Square(hdu 数论 4394,bfs求后n位相同)

Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 462 Accepted Submission(s): 225

Problem Description

Given an integer N,you should come up with the minimum nonnegative integer M.M meets the follow condition: M2%10x=N (x=0,1,2,3....)

 

Input

The first line has an integer T( T< = 1000), the number of test cases.
For each case, each line contains one integer N(0<= N <=109), indicating the given number.

 

Output

For each case output the answer if it exists, otherwise print “None”.

 

Sample Input

3

3

21

25

 

Sample Output

None

11

5

 

Source

2012 Multi-University Training Contest 10

 

Recommend

zhuyuanchen520

 

 思路转自某神,,,看了才会的,,,,哎。。。。。继续加油!

 

M^2%10^x=N (x=0,1,2,3....),给你一个N,求M,x为0,1,2,3....其中一个数就行了。找不到M输出None
也就是求N是某个数的平方的后缀(包括本身)。
思路:
BFS。
首先证明出N位后缀只与M的后N位有关。
比如三位数100a+10b+c平方后展开为
10000a^2+2000ab+100b^2+200ac+20bc+c^2
很显然,平方后的最后一位只与c有关
最后两位只与bc有关,最后三位abc都有关
可以类推出上面的结论。
然后从个位开始广搜,逐位满足N, 每扩展
要判断一次是否为解。(有可能后面位数满足
的同时前面位数自动满足了)。注意有解时一
定要搜索这一层的所有解,输出最小解 。
PS:要注意小细节如1000000000的情况,挂在这里好久。。。

View Code
  1 #include<stdio.h>
  2 #include<stack>
  3 #include<stdlib.h>
  4 #include<cmath>
  5 #include<iostream>
  6 #include<map>
  7 #include<queue>
  8 #include<set>
  9 #include<string.h>
 10 #define M 200010
 11 #define INF 2139062143
 12 #define LL __int64
 13 using namespace std;
 14 
 15 class node
 16 {
 17     public:
 18     int id;
 19     LL num;  //id是位置,从个位开始1,2.。。。num是这个id位数
 20     node(int a,LL b)
 21     {
 22         id = a;
 23         num = b;
 24     }
 25 };
 26 
 27 LL weishu(LL x)  //求x是几位数
 28 {
 29     LL i = 1,j = 0;
 30     while(x/i!=0)
 31     {
 32         i *= 10;
 33         ++j;
 34     }
 35 
 36     return j;
 37 }
 38 
 39 bool eq(LL a,LL b,int k)        //判断a和b的最后k位是否相同
 40 {
 41     while(k--)
 42     {
 43         if(a%10!=b%10) return false;
 44 
 45         a = a/10;
 46         b = b/10;
 47     }
 48     return true;
 49 }
 50 
 51 int main()
 52 {
 53     int i,T;
 54     LL n;
 55     queue<node>q;
 56     cin>>T;
 57     while(T--)
 58     {
 59         LL ans = 0;
 60         scanf("%I64d",&n);
 61 
 62         while(!q.empty()) q.pop();
 63         bool flag = false;
 64         int sumid = 0,j = 1;
 65         sumid = weishu(n);
 66         //cout<<sumid<<endl;
 67 
 68         for(i = 0;i<=9;i++)
 69         {
 70             LL d = i*i;
 71             if(d == n||d%10 == n)
 72             {
 73                 flag = true;
 74                 ans = i;
 75                 break;
 76             }
 77             if(eq(d,n,1))
 78             {
 79                 q.push(node(1,(LL)i));
 80                 //cout<<"1 "<<i<<endl;
 81             }
 82         }
 83         j = 1;
 84 
 85         //if(q.empty()) cout<<"kong"<<endl;
 86         //else cout<<q.front().num<<endl;
 87         while(!q.empty()&&!flag)
 88         {
 89             int iid = q.front().id;
 90             LL k = q.front().num;
 91            // cout<<iid<<" "<<k<<endl;
 92             q.pop();
 93             if(iid > sumid) break;
 94             if(iid == sumid)
 95             {
 96                 if(k == n)
 97                 {
 98                     flag = true;
 99                     ans = k;
100                     break;
101                 }
102             }
103 
104             for(i = 0;i<=9;i++)
105             {
106                 LL dd = (i*pow(10,iid) + k),d = 0;
107                 d = dd*dd;
108                 if(eq(d,n,iid+1))
109                 {
110                     if(eq(d,n,sumid))
111                     {
112                         flag = true;
113                         ans = dd;
114                         for(;;)
115                         {
116                             if(q.empty()) break;
117                             int newiid = q.front().id;
118                             LL newk = q.front().num;
119                             q.pop();
120                             if(newiid!=iid) break;
121                             for(j = 1;j<=9;j++)
122                             {
123                                 LL newdd = (j*pow(10,newiid) + newk),newd = 0;
124                                 newd = newdd*newdd;
125                                 if(eq(newd,n,sumid) && ans > newdd)
126                                 {
127                                     ans = newdd;
128                                 }
129                             }
130                         }
131                         break;
132                     }
133                     // cout<<iid + 1<<" "<<dd<<endl;
134                     if(iid<sumid) q.push(node(iid+1,dd));
135                 }
136                    //???????????????????????//
137             }
138             if(flag) break;
139         }
140         if(flag) printf("%I64d\n",ans);
141         else printf("None\n");
142     }
143     return 0;
144 }

 

好的,关于 HDU4992 求所有原根的问题,我可以给出以下解答: 1. 首先,我们需要知道什么是原根。原根是指模 n 意义下,所有与 n 互质的数 a 的最小正整数 k 次幂对 n 取模的值覆盖了所有与 n 互质的数。简单来说,就是如果一个数 a 是模 n 意义下的原根,那么 a 的任何正整数次幂对 n 取模的值都不相同,且能覆盖所有与 n 互质的数。 2. 为了求模 n 意义下的所有原根,我们需要先求出与 n 互质的数的个数 phi(n)。phi(n) 可以使用欧拉函数求出。 3. 然后,我们需要枚举模 n 意义下的所有数,判断它是否是原根。具体来说,对于每个 a,我们需要判断 a 的每个小于 phi(n) 的正整数次幂对 n 取模的值是否都不相同,且能覆盖所有与 n 互质的数。如果是,那么 a 就是模 n 意义下的原根。 4. 代码实现可以参考以下 Java 代码: ``` import java.util.*; public class Main { static int gcd(int a, int b) { return b == 0 ? a : gcd(b, a % b); } static int phi(int n) { int res = n; for (int i = 2; i * i <= n; i++) { if (n % i == 0) { res = res / i * (i - 1); while (n % i == 0) { n /= i; } } } if (n > 1) { res = res / n * (n - 1); } return res; } static int pow(int a, int b, int mod) { int res = 1; while (b > 0) { if ((b & 1) != 0) { res = res * a % mod; } a = a * a % mod; b >>= 1; } return res; } static boolean check(int a, int n, int phi) { for (int i = 1, j = pow(a, i, n); i <= phi; i++, j = j * a % n) { if (j == 1) { return false; } } return true; } public static void main(String[] args) { Scanner scanner = new Scanner(System.in); while (scanner.hasNext()) { int n = scanner.nextInt(); int phi = phi(n); List<Integer> ans = new ArrayList<>(); for (int i = 1; i < n; i++) { if (gcd(i, n) == 1 && check(i, n, phi)) { ans.add(i); } } Collections.sort(ans); for (int x : ans) { System.out.print(x + " "); } System.out.println(); } } } ``` 其中,gcd 函数用于求最大公约数,phi 函数用于求欧拉函数,pow 函数用于快速幂求模,check 函数用于判断一个数是否是原根。在主函数中,我们依次读入每个 n,求出 phi(n),然后枚举模 n 意义下的所有数,判断它是否是原根,将所有原根存入一个 List 中,最后排序输出即可。 希望我的回答能够帮到你,如果你有任何问题,欢迎随时提出。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值