被7整除
Posted 绿色代码
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了被7整除相关的知识,希望对你有一定的参考价值。
时间限制:C/C++语言 2000MS;其它语言 4000MS
内存限制:C/C++语言 65536KB;其它语言 589824KB
题目描述:
小萌非常喜欢能被7整除的数字,比如7,21,121996,等等。有一天她得到了n个 正整数,她想用这些数制造出更多的能够被7整除的数。于是她从这n个数中选出两个数,然后将一个数写在另一个数的前面,以此得到一个新的数。按这种方法她一共可以得到2X{n,2}个数,她想知道在这些数中,有多少个是能被7整除的。
输入
第一行包含一个整数n。2≤n≤10的5次方
第二行包含n个正整数ai。1 ≤ai≤10的9次方
第二行包含n个正整数ai。1 ≤ai≤10的9次方
输出
输出对应的答案。
样例输入
3
127 1996 12
样例输出
4
Hint
一共有4种组合方式,其中:把12写在1996前面得到121996;把127写在12前面得到12712;把1996写在12前面得到199612;把1996写在127前面得到1996127;都是可以被7整除的,其余的组合方式不能被7整除。
输出对应的答案。
样例输入
3
127 1996 12
样例输出
4
Hint
一共有4种组合方式,其中:把12写在1996前面得到121996;把127写在12前面得到12712;把1996写在12前面得到199612;把1996写在127前面得到1996127;都是可以被7整除的,其余的组合方式不能被7整除。
代码----------能处理10万条数据!
一.纯代码版
一.纯代码版
#include<iostream>
#include<fstream>
#include<ctime>
using namespace std;
int main()
{
clock_t start = clock();
int n,i,j,zc_num=0,cf_num=0;
ifstream in("makebigdata.txt");
//ifstream in("test2.txt");
in>>n;
int *ys=new int[n],*ws=new int[n],arr_same[100]={0};
int arr_ys[10]={3,2,6,4,5,1,3,2,6,4};
int arr_check[370]={0};
for(i=0;i<370;i++)
if(i%7==0)
arr_check[i]=1;
j=0;
for(i=0;i<n;i++)
{
int ws_temp,ys_temp,temp;
in>>temp;
if(temp%7)
{
ys_temp=temp%7;
ws_temp=-1;
while(temp)
{
temp/=10;
ws_temp++;
}
if(arr_same[ws_temp*10+ys_temp]>=1)
{
arr_same[ws_temp*10+ys_temp]++;
cf_num++;
}
else
{
ys[j]=ys_temp;ws[j]=ws_temp;
arr_same[ws_temp*10+ys_temp]=1;
j++;
}
}
else
zc_num++;
}
int num=0;
num=zc_num*(zc_num-1);
for(i=0;i<n-zc_num-cf_num-1;i++)
for(j=i+1;j<n-zc_num-cf_num;j++)
{
int num_temp=num+arr_check[arr_ys[ws[j]]*ys[i]+ys[j]];
if(num_temp>num)
num+=arr_same[ws[i]*10+ys[i]]*arr_same[ws[j]*10+ys[j]];
num_temp=num+arr_check[arr_ys[ws[i]]*ys[j]+ys[i]];
if(num_temp>num)
num+=arr_same[ws[i]*10+ys[i]]*arr_same[ws[j]*10+ys[j]];
}
for(i=0;i<n-zc_num-cf_num;i++)
if(arr_check[arr_ys[ws[i]]*ys[i]+ys[i]]==1)
num+=arr_same[ws[i]*10+ys[i]]*(arr_same[ws[i]*10+ys[i]]-1);
cout<<num<<endl;
clock_t ends = clock();
cout <<"Running Time : "<<(double)(ends - start)/ CLOCKS_PER_SEC << endl;
return 0;
}
运行效率刚刚滴!
二.注释版
三.生成测试数据代码
二.注释版
#include<iostream>
#include<fstream>
#include<ctime>
using namespace std;
int main()
{
clock_t start = clock();
int n,i,j;
ifstream in("makebigdata.txt");
//ifstream in("test2.txt");
in>>n;//读入整数个数n
int *ys=new int[n]; //整数对7的余数
int *ws=new int[n];//整数的位数
/*
比如:233456和788993 组成的数为:
233456788993(数A1)=788993(数D)233456(数B)
=788993(数D)*1000000(数C)+233456(数B)
233456788993(数A2)=233456(数B)788993(数D)
=233456(数B)*1000000(数C)+788993(数D)
其中,数C比数D多一位,B和D对7整除分别有两种情况:
[B1]:被7整除 [B2]:不能被7整除
[D1]:被7整除 [D2]:不能被7整除
以上面的数A2为例,四种组合:[B_Y],[C_Y],[D_Y]取值为[0,6],其中C_Y一定不为零,原因看下文,
[B1][D1]
[B_Y]*[C_Y]+[D_Y]=0*[C_Y]+0=0 被7整除
[B1][D2]
[B_Y]*[C_Y]+[D_Y]=0*[C_Y]+[D_Y]=[D_Y] 不能被7整除
[B2][D1]
[B_Y]*[C_Y]+[D_Y]=[B_Y]*[C_Y]+0=[B_Y]*[C_Y] 由于7是质数,故[B_Y]*[C_Y]一定不是7的倍数
不能被7整除
[B2][D2]=[B_Y]*[C_Y]+[D_Y] 不确定能否被7整除
因此本程序只需考虑第一种和第四种组合
推理如下(以上面的数A2为例):
(商) (余数)
[A]/7=[A_Z]...[A_Y]
[B]/7=[B_Z]...[B_Y]
[C]/7=[C_Z]...[C_Y]
[D]/7=[D_Z]...[D_Y]
[A]%7=([B]*[C]+[D])%7
=( ( ([B_Z]*7 + [B_Y])* [C] )%7 + [D]%7 )%7
=( ( [B_Z]*7*[C] + [B_Y] * [C] )%7 + [D_Y] )%7
=( ( 0 + [B_Y] * [C] %7 )%7 + [D_Y] )%7
=( [B_Y]*[C] %7 + [D_Y] )%7
=( [B_Y]*([C_Z]*7+[C_Y]) %7 + [D_Y]%7 )%7
=( ([B_Y]*[C_Z]*7 +[B_Y]*[C_Y]) %7 + [D_Y]%7 )%7
=( (0 +[B_Y]*[C_Y]%7)%7 + [D_Y]%7 )%7
=( [B_Y]*[C_Y] %7 + [D_Y]%7 )%7
=( [B_Y]*[C_Y] + [D_Y] )%7
说明:arr_ys数组的下标表示整数的位数,为方便计算,比实际位数少取一位
存储的内容为数[C]对7的余数[C_Y]
下文中用法解释:arr_ys[ws[j]]*ys[i]+ys[j]
ws[j]:整数的位数,为便于计算比实际位数少一位,如678位数为2位
ws[j]=0,说明数D为1位数,数C=10
...
...
...
ws[j]=9,说明数D为10位数,输C=10000000000
arr_ys[ws[j]]=[C_Y]根据传入的整数位数构造余数
arr_ys[ws[j]] * ys[i] + ys[j]
= [C_Y] * [B_Y]] + [D_Y]
*/
//构造C_Y集合
int arr_ys[10]={
10%7,
100%7,
1000%7,
10000%7,
100000%7,
1000000%7,
10000000%7,
100000000%7,
1000000000%7,
1000000000%7*10%7
};
//静态化C_Y集合
//int arr_ys[10]={3,2,6,4,5,1,3,2,6,4};
//arr_check用来判断[C_Y]*[B_Y]]+[D_Y]能不能被7整除,初始化为0,表示不能被7整除
//最大元素个数与被除数有关,本程序中7的最大余数为6,则arr_check数组的最大元素个数为6*6*6
int arr_check[6*6*6+1]={0};
for(i=0;i<6*6*6+1;i++)
if(i%7==0)//能被7整除设置元素值为1
arr_check[i]=1;
/*
统计相同特征数据的重复次数
相同特征的说明,如果数[B]和数[D]具有相同的位数,且对7的余数也相同
我们就认为这两数具有相同的特征,是重复数据
从上文逻辑推理中,我们看到,数[A]对7的余数只与[B_Y],[C_Y]和[D_Y]有关
下文中arr_same[ws_temp*10+ys_temp]的说明:
ws_temp:当前读取数据的位数,比实际位数少1位,由于为int型数据,最大10位
故ws_temp的取值范围为:0-9
ys_temp:当前读取数据对7的余数,取值范围为:0-6
arr_same[ws_temp*10+ys_temp]:具有相同位数和余数的数据出现的次数
*/
int arr_same[100]={0};
//记录能被7整除的数据的个数
int zc_num=0;
//记录不能被7整除具有相同特征的数据的重复次数
int cf_num=0;
j=0;
//循环读取数据(遍历数据)
for(i=0;i<n;i++)
{
int ws_temp,ys_temp;
int temp;
in>>temp;
if(temp%7==0)//被7整除,计数
zc_num++;
else
{
ys_temp=temp%7;//被7除的余数
ws_temp=-1;
while(temp)//计算整数的位数,比实际位数少一位
{
temp/=10;
ws_temp++;
}
//根据当前读取数据的位数和余数特征在arr_same中判断是否已经有该特诊的数据存在
if(arr_same[ws_temp*10+ys_temp]>=1)//已存在,
{
arr_same[ws_temp*10+ys_temp]++;//更新该特诊的重复次数
cf_num++;//更新总数据的重复次数
}
else//不存在,记录该数据的特征
{
ys[j]=ys_temp;//记录对7余数
ws[j]=ws_temp;//记录位数
j++;
arr_same[ws_temp*10+ys_temp]=1;//设置该特诊的重复次数
}
}
}
//统计整个输入数据中两两组合能被7整除的组合个数
int num=0;
//能被整除的组合:[B1][D1]和[D1][B1]
num=zc_num*(zc_num-1);
//不确定的组合:[B2][D2]和[D2][B2]
//能被7整除的数和arr_same[]数组中已具有相同特征的数不会再在ys[]和ws[]数组中记录它们的位数和对7余数
//因此ys[]和ws[]数组中记录的都是彼此不具有相同特征的数据的位数和对7余数
for(i=0;i<n-zc_num-cf_num-1;i++)
for(j=i+1;j<n-zc_num-cf_num;j++)
{
//[B2][D2]组合
int num_temp=num+arr_check[arr_ys[ws[j]]*ys[i]+ys[j]];
//下述条件成立:
//arr_check[arr_ys[ws[j]]*ys[i]+ys[j]]值为1,即[B2][D2]组合能被7整除
//那么分别和B2,D2具有相同特征的两个数的组合也能被7整除
//下文中arr_same[ws[i]*10+ys[i]]的值为和[B2]具有相同特征的数据的个数,包括[B2]
//arr_same[ws[j]*10+ys[j]]的值为和[D2]具有相同特征的数据的个数,包括[D2]
if(num_temp>num)
num+=arr_same[ws[i]*10+ys[i]]*arr_same[ws[j]*10+ys[j]];
//[D2][B2]组合
num_temp=num+arr_check[arr_ys[ws[i]]*ys[j]+ys[i]];
//解释参考[B2][D2]组合
if(num_temp>num)
num+=arr_same[ws[i]*10+ys[i]]*arr_same[ws[j]*10+ys[j]];
}
//[B2][B2]或者[D2][D2]组合,具有相同特征的数据内部自我两两组合
//判断能不能被7整除
for(i=0;i<n-zc_num-cf_num;i++)
//[B2][B2]或者[D2][D2]组合能被7整除,类似于[B1][D1]和[D1][B1]计数
if(arr_check[arr_ys[ws[i]]*ys[i]+ys[i]]==1)
num+=arr_same[ws[i]*10+ys[i]]*(arr_same[ws[i]*10+ys[i]]-1);
cout<<num<<endl;
clock_t ends = clock();
cout <<"Running Time : "<<(double)(ends - start)/ CLOCKS_PER_SEC << endl;
return 0;
}
三.生成测试数据代码
#include<iostream>
#include<fstream>
#include<ctime>
using namespace std;
int main()
{
int n=100000;
ofstream out("makebigdata.txt");
out<<n<<endl;
srand((int)time(0));
for(int i=1;i<=n;i++)
out<<RAND_MAX*rand()+rand()<<" ";
return 0;
}
以上是关于被7整除的主要内容,如果未能解决你的问题,请参考以下文章
C语言编程:输出1000以内能被3整除的奇数以及这些奇数的和,怎么写?
C语言试题十三之求出1到100之内能被7或者11整除,但不能同时被7和11整除的所有整书,并将他们放在a所指的数组中,通过n返回这些数的个数。
C语言试题十三之求出1到100之内能被7或者11整除,但不能同时被7和11整除的所有整书,并将他们放在a所指的数组中,通过n返回这些数的个数。