任意给定一个正整数N,求一个最小的正整数M(M>1),使得N*M的十进制表示形式里只含有1和0。
解法二:由于没有直接的数学方法能帮我们直接得到M的值,所以我们只能进行搜索。由于相对M,乘积N*M具有明显的特征,需要搜索的空间要小很多,所以我们对乘积N*M进行搜索。如果N*M的结果有K位,则要循环2^K次,我们发现K的结果能轻易超过40,所以这个运行时间还是相当长。同余运算具有等价关系,mod N = i(0<=i<N)构成了N个等价类,将正整数集进行划分。对于每个等价类,我们只需要判断其中最小的元素加上10^K是否能被N整除,这样搜索空间就从2^K次减少到(K-1)*N步,而N的值一般要远远小于M的值,但要O(N)的空间复杂度。
由于无论M还是N*M的位数都相当大,所以我们用大整数表示M和N*M。由于要N个大整数,所以N不能为大整数,即其值最好取一百万以内。
代码实现入下:
#include<iostream>
#include<cmath>
#include<vector>
using namespace std;
bool FindNumber(int N,vector<int> *BigInt);
int main()
{
int N,i;
cout<<"Input a positive integer: ";
cin>>N;
vector<int> *BigInt=new vector<int>[N];//用来存放余数为0 ~ N最小数字,数字表示,如整数1001,则存为1001=10^0+10^3=(0,3),适合大数的表示
for(i=0;i<N;i++)
BigInt[i].clear();
bool found=FindNumber(N,BigInt);
if(found)
{
int len=BigInt[0][BigInt[0].size()-1]+1;
char *product=new char[len+1];
int product2=0;
for(i=0;i<len;i++)
product[i]='0';
product[len]='\0';
vector<int>::iterator iter;
for(iter=BigInt[0].begin();iter!=BigInt[0].end();iter++)
{
product2=product2+pow(10,*iter);
product[*iter]='1';
}
int j=len-1;
i=0;
while(i<j)
{
char tmp=product[j];
product[j]=product[i];
product[i]=tmp;
i++;
j--;
}
int M=product2/N;
//product和product2都对应着乘积结果,但是product2对应着整型,乘积过大时,product2可能不会得到正确的结果;
//product对应着乘积的字符串,可以表示大数的乘积结果,M为product2/N,即为要求的数,当product2溢出时,不是正确的结果,
//那种情况下,需要用product/N,其中product为乘积的字符串表示,这里没有求解,读者可以自行解决。
cout<<N<<" * "<<M<<" = "<<product<<" , "<<product2<<endl;
delete []product;
}
else
cout<<"Can not find M!"<<endl;
delete []BigInt;
return 0;
}
bool FindNumber(int N,vector<int> *BigInt)
{
int i,j,k;
BigInt[1].push_back(0);
int NoUpdate=0;
for(i=1,j=10%N; ; i++,j=(j*10)%N)
{
bool flag=false;
if(BigInt[j].size()==0)
{
flag=true;
// BigInt[j]=10^i,(10^i)%N=j
BigInt[j].clear();
BigInt[j].push_back(i);
}
for(k=1;k<N;k++)
{
//有新的余数出现
if((BigInt[k].size()>0)&&(i>BigInt[k][BigInt[k].size()-1])
&&(BigInt[(k+j)%N].size()==0))
{
//BigInt[(k+j)%N]=10^i+BigInt[k]
flag=true;
BigInt[(k+j)%N]=BigInt[k];
BigInt[(k+j)%N].push_back(i);
}
}
if(flag==false)
NoUpdate++;
else
NoUpdate=0;
//如果经过一个循环节都没能对BigInt进行更新,就是无解,跳出,
//若有N次没更新过余数信息,则存在c>=0,10^(c+1)modN,...,10^(c+N)modN中必有两个是相等的,
//那么继续进行下去也不会再更新了
//或者BigInt[0]!=NULL,已经找到解,也跳出.
if(NoUpdate==N||BigInt[0].size()>0)//若有N次没更新过余数信息,则存在c>=0,10^(c+1)modN,...,10^(c+N)modN中必有两个是相等的,那么继续进行下去也不会再更新了
break;
}
if(BigInt[0].size()==0)
return false;
else
return true;
}
我们可以证明对于任意的N,一定存在M,使得N*M的乘积的十进制表示只有0和1。证明过程见:http://blog.csdn.net/jcwkyl/article/details/3859155
任意给定一个正整数N,求一个最小的正整数M(M>1),使得N*M的十进制表示形式里只含有1和0。的更多相关文章
- 38 写一个函数,求一个字符串的长度,在main函数中输入字符串,并输出其长度。
题目:写一个函数,求一个字符串的长度,在main函数中输入字符串,并输出其长度. public class _038PrintLength { public static void main(Stri ...
- 写一个函数,求一个字符串的长度,在main函数中输入字符串,并输出其长度
import java.util.Scanner; /** * [程序38] * * 题目:写一个函数,求一个字符串的长度,在main函数中输入字符串,并输出其长度. * * @author Jame ...
- 谷歌面试题:输入是两个整数数组,他们任意两个数的和又可以组成一个数组,求这个和中前k个数怎么做?
谷歌面试题:输入是两个整数数组,他们任意两个数的和又可以组成一个数组,求这个和中前k个数怎么做? 分析: "假设两个整数数组为A和B,各有N个元素,任意两个数的和组成的数组C有N^2个元素. ...
- 给定一个数组,求如果排序之后,相邻两数的最大差值,要求时间复杂度为O(N),且要求不能用非基于比较的排序
题目: 给定一个数组,求如果排序之后,相邻两数的最大差值,要求时间复杂度为O(N),且要求不能用非基于比较的排序 public static int maxGap(int nums[]) { if ( ...
- 【C语言】求旋转数组的最小数字,输入一个递增排序的数组的一个旋转,输出其最小元素
//求旋转数组的最小数字,输入一个递增排序的数组的一个旋转,输出其最小元素 #include <stdio.h> #include <string.h> int find_mi ...
- Bellman_Ford算法(求一个点到任意一点的最短距离)
单源最短路问题是固定一个起点,求它到任意一点最短路的问题. 记从起点出发到顶点 i 的最短距离为d[i],则有以下等式成立 d[i]=min{d[j]+(从j到 i 的边的权值) 看代码 #inclu ...
- 求一个集合的所有真子集 Python
给定一个集合,元素均为正整数且不重复,求该集合的所有子集 # -*- coding: utf-8 -*- """ Created on Tue Oct 10 09:04: ...
- poj1190,DFS/已知一个等式,求另一个最小值
7月17日是Mr.W的生日,ACM-THU为此要制作一个体积为Nπ的M层生日蛋糕,每层都是一个圆柱体. 设从下往上数第i(1 <= i <= M)层蛋糕是半径为Ri, 高度为Hi的圆柱. ...
- 求一个数组中第K小的数
面试南大夏令营的同学说被问到了这个问题,我的第一反应是建小顶堆,但是据他说用的是快排的方法说是O(n)的时间复杂度, 但是后来经过我的考证,这个算法在最坏的情况下是O(n^2)的,但是使用堆在一般情况 ...
随机推荐
- StrPCopy与StrPas功能正好相反,作用是与C语言字符串和Delphi的String相互转化
StrPCopy = Copies an AnsiString (long string) to a null-terminated string.function StrPCopy(Dest: PA ...
- Qt5 基于TCP传输的发送/接收文件服务器(支持多客户端)
一.实现功能 1.服务器端选择待发送的文件,可以是多个 2.开启服务器,支持多客户端接入,能够实时显示每个客户端接入状态 3.等待所有客户端都处于已连接状态时,依次发送文件集给每个客户端,显示每个客户 ...
- Android中ListView无法点击
Android中ListView无法点击 转自:http://xqjay19910131-yahoo-cn.iteye.com/blog/1319502 问题描述: ListView中Item加入 ...
- 关于App的一些迷思以及一些动画效果开源库的推荐
http://www.open-open.com/lib/view/open1427856817396.html
- Android EditText小结
防止EditText获取焦点弹出输入法 android:focusable="true" android:focusableInTouchMode="true" ...
- 10个简单步骤,完全理解SQL
此文章为转载 1. SQL 是一种声明式语言 首先要把这个概念记在脑中:“声明”. SQL 语言是为计算机声明了一个你想从原始数据中获得什么样的结果的一个范例,而不是告诉计算机如何能够得到结果.这是不 ...
- 反射消除String类对象的不可变特性
大家都知道,在JAVA中字符串一旦声明就不可改变,如果尝试修改字符串的内容,将会重新实例化一个新的字符串对象,这也是为了安全性和效率. 由于字符串在程序之中被大量使用,所以JAVA引入了一个字符串常量 ...
- Molecule to atoms
For a given chemical formula represented by a string, count the number of atoms of each element cont ...
- 前端中的SEO
前端中的SEO: mate.title META标签分两大部分:HTTP标题信息(HTTP-EQUIV)和页面描述信息(NAME). <Meta name="Keywords" ...
- sqlmap新手注入
一 什么是sqlmap sqlmap is an open source penetration testing tool that automates the process of detectin ...