zoukankan      html  css  js  c++  java
  • 被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次方
    输出 
           输出对应的答案。

    样例输入
           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;
    }
  • 相关阅读:
    PTA考试几点注意事项
    网易云信在融合通信场景下的探索和实践之 SIPGateway 服务架构
    破旧立新,精准测试之道
    从 0 到 1 构建实时音视频引擎
    云信小课堂|如何实现音视频通话
    Python 回调函数实现异步处理
    数据结构--链表--约瑟夫问题
    Python 轻松实现ORM
    leetcode 递归编程技巧-链表算法题
    Tornado 初识
  • 原文地址:https://www.cnblogs.com/zhaopeng938/p/7532066.html
Copyright © 2011-2022 走看看