大整数除法
L1-046. 整除光棍
这里所谓的“光棍”,并不是指单身汪啦~ 说的是全部由1组成的数字,比如1、11、111、1111等。传说任何一个光棍都能被一个不以5结尾的奇数整除。比如,111111就可以被13整除。 现在,你的程序要读入一个整数x,这个整数一定是奇数并且不以5结尾。然后,经过计算,输出两个数字:第一个数字s,表示x乘以s是一个光棍,第二个数字n是这个光棍的位数。这样的解当然不是唯一的,题目要求你输出最小的解。
**提示:**一个显然的办法是逐渐增加光棍的位数,直到可以整除x为止。但难点在于,s可能是个非常大的数 —— 比如,程序输入31,那么就输出3584229390681和15,因为31乘以3584229390681的结果是111111111111111,一共15个1。
** 输入格式:**
输入在一行中给出一个不以5结尾的正奇数x(< 1000)。
** 输出格式:**
在一行中输出相应的最小的s和n,其间以1个空格分隔。
输入样例:
31
输出样例:
3584229390681 15
属性 | 要求 | 属性 | 要求 |
---|---|---|---|
时间限制 | 400 ms | 内存限制 | 65536 kB |
代码长度限制 | 8000 B | 判题程序 | Standard |
解析:
看到题目的提示就知道,绝对不可以从1开始试吧。我查了一下,(=゚ω゚)ノ发现了大整数除法这种巧妙的东西。
回想一下小时候学的除法。就是拿着除数从被除数的第一位开始算,化除法为减法的思路。
先看题目要求,输入一个数x,让你输出两个数a和n,理一下:某个光棍数 = a × x , n =a×x,n =a×x,n为这个光棍数的位数。
(如果想不明白,可以看代码后边的补充)
答案:
#include<iostream>
using namespace std;
int main()
{
int x,n,s=0,flag=0;
cin>>x;
for(n=1;;n++)//n统计有几个1
{
s=s*10+1;
if(s>=x)//可以除的时候
{
flag=1;//做标记,已经开始输出了
cout<<s/x;//能除的商
}
else if(flag==1)//s<x&&flag==1也就是说已经开始输出了但是s此时小于x,那么就上0
cout<<0;
s=s%x;///记录余数
if(s==0)///能除尽则跳出
break;
}
cout<<" "<<n;;///输出位数
return 0;
}
补充:
以101为例子计算:
flag输出标志,用于标记是否开始输出了,如果开始输出,之后flag都不会改变了。
s ,s >= x , s % x都是像小学学的除法一个作用,自己理解一下啦(●’◡’●)ノ♥ 。
大整数乘法
题目内容:
求两个不超过200位的非负整数的积。
输入格式:
有两行,每行是一个不超过200位的非负整数,没有多余的前导0。
输出格式:
一行,即相乘后的结果。结果里不能有多余的前导0,即如果结果是342,那么就不能输出为0342。
输入样例:
12345678900
98765432100
输出样例:
1219326311126352690000
解析:
就是普通乘法式子。
答案:
#include<iostream>
#include<cmath>
#include<string>
#include<cstring>
using namespace std;
int main()
{
string a,b;
cin>>a>>b;
int n=a.length()+b.length();
int *s=new int[n];
memset(s,0,n*sizeof(int)); //初始化数组
for(int i=0;i<a.length();i++)
{
for(int j=0;j<b.length();j++)
{
s[i+j+1]+=(a[i]-'0')*(b[j]-'0'); //想一下乘法怎么写的
}
}
for(int i=a.length()+b.length()-1;i>0;i--) //乘法进位
{
if(s[i]>9)
{
s[i-1]+=s[i]/10;
s[i]%=10;
}
}
int c=0;
for(int i=0;i<n;i++)
{
if(s[i]==0)
c++;
else
break;
}
for(int i=c;i<n;i++)
{
cout<<s[i];
}
if (c==n)
{
cout<<0;
}
return 0;
}