• 蓝桥杯历年试题 矩阵翻硬币


    问题描述
      小明先把硬币摆成了一个 n 行 m 列的矩阵。

      随后,小明对每一个硬币分别进行一次 Q 操作。

      对第x行第y列的硬币进行 Q 操作的定义:将所有第 i*x 行,第 j*y 列的硬币进行翻转。

      其中i和j为任意使操作可行的正整数,行号和列号都是从1开始。

      当小明对所有硬币都进行了一次 Q 操作后,他发现了一个奇迹——所有硬币均为正面朝上。

      小明想知道最开始有多少枚硬币是反面朝上的。于是,他向他的好朋友小M寻求帮助。

      聪明的小M告诉小明,只需要对所有硬币再进行一次Q操作,即可恢复到最开始的状态。然而小明很懒,不愿意照做。于是小明希望你给出他更好的方法。帮他计算出答案。
    输入格式
      输入数据包含一行,两个正整数 n m,含义见题目描述。
    输出格式
      输出一个正整数,表示最开始有多少枚硬币是反面朝上的。
    样例输入
    2 3
    样例输出
    1
    数据规模和约定
      对于10%的数据,n、m <= 10^3;
      对于20%的数据,n、m <= 10^7;
      对于40%的数据,n、m <= 10^15;
      对于10%的数据,n、m <= 10^1000(10的1000次方)。
     
    思路:
    杭电以前做过一道一维的题目(灯泡的开闭,具体题目名记不到了),先看一维。因为和顺序无关,我们从小到达进行,对于第x个棋子它的最终状态取决与1-x约数个数的奇偶,而只有平方数的约数个数是奇数,所以转变成求1-n中平方数个数,如果有k个平方数,最大的平方数为k^2,k^2<=n,所以k为sqrt(n)取整。
    拓展到二维原理是一样的,只不过需要同时满足x,y均为平方数,那么这样的数的个数即为(1-n的平方数个数)*(1-m的平方数个数)。
    观察一下题目的数据范围,上高精度,扔模板。
    #include <iostream>
    #include <cstdio>
    #include <string>
    #include <cmath>
    #define LL long long int
    using namespace std;
    struct numlist
    {
        static const int L=1100;
        int a[L];
        int len;
        void ini(string s)//字符串输入
        {
            fill(a,a+L,0);
            for(int i=s.length()-1;i>=0;i--)
                a[s.length()-i-1]=s[i]-'0';
            len=s.length();
        }
        void ini(long long int num)//数字输入
        {
            fill(a,a+L,0);
            len=0;
            if(num==0) len++;
            while(num)
            {
                a[len++]=num%10;
                num/=10;
            }
        }
        void updateBit()//更新位数,约定0的位数是0
        {
            len=0;
            for(int i=0; i<L; i++)
            {
                if(a[i]!=0)
                    len=i+1;
                if(a[i]>=10)
                {
                    int temp=a[i]/10;
                    a[i]%=10;
                    a[i+1]+=temp;
                }
                if(a[i]<0)
                {
                    int temp=-(a[i]%10!=0)+a[i]/10;
                    a[i]%=10;
                    if(a[i]<0) a[i]+=10;
                    a[i+1]+=temp;
                }
            }
        }
        void print()//测试输出
        {
            for(int i=len-1;i>=0;i--)
                cout<<a[i];
            cout<<endl;
            /*
            for(int i=len-1;i>=0;i--)
                printf("%d",a[i]);
            printf("
    ");
            */
        }
    };
    numlist Add(numlist a,int num)
    {
        int p=0;
        while(num)
        {
            a.a[p++]+=num%10;
            num/=10;
        }
        a.updateBit();
        return a;
    }
    numlist Add(numlist a,numlist b,int f)
    {
        int mx=a.len;
        if(b.len>mx) mx=b.len;
        for(int i=0;i<mx;i++)
            a.a[i]+=b.a[i]*f;
        a.updateBit();
        return a;
    }
    int fix=0;
    numlist Bmut(numlist a,numlist b)
    {
        numlist c;
        c.ini(0);
        for(int i=0; i<a.len; i++)
            for(int j=0; j<b.len; j++)
                c.a[i+j]+=a.a[i]*b.a[j];
    
        c.updateBit();
        return c;
    }
    int BitCmp(numlist a,numlist b)//1:a>b,-1:a<b,0:a==b
    {
        if(a.len!=b.len)
            return a.len>b.len?1:-1;
        for(int i=a.len-1;i>=0;i--)
            if(a.a[i]!=b.a[i])
                return a.a[i]>b.a[i]?1:-1;
        return 0;
    }
    numlist Sqrt(numlist a)
    {
        numlist rec,num100,high,preBit;
        num100.ini(100);
        string ans="";//顺序记录每一位
        int pos=a.len-(!(a.len%2)+1);
        numlist temp;
        int initNum=0;
        for(int i=a.len-1;i>=pos;i--)
            initNum*=10,initNum+=a.a[i];
    
        ans+=sqrt(initNum)+'0';
        preBit.ini(ans);
        initNum-=(int)sqrt(initNum)*(int)sqrt(initNum);
        //cout<<initNum<<endl;
        temp.ini(initNum);//部分余数
        pos-=2;
        for(;pos>=0;pos-=2)
        {
            ans+='0';
            for(int i=preBit.len;i>0;i--)
                preBit.a[i]=preBit.a[i-1];
            preBit.a[0]=0;
            preBit.len++;
    
            high=preBit;
            high=Add(high,high,1);
            temp=Bmut(temp,num100);
            temp=Add(temp,a.a[pos]+a.a[pos+1]*10);
            numlist pn,pn1;
            numlist pnow,ppre;
            int p=5;
            do
            {
                pn.ini(p),pn1.ini(p-1);
    
                pnow=Bmut(Add(high,p),pn);
    
                ppre=Bmut(Add(high,p-1),pn1);
                if(BitCmp(temp,ppre)<0)
                    p--;
                else if(BitCmp(pnow,temp)<=0)
                    p++;
                else
                    break;
            }while(1);
            p--;
            preBit.a[0]=p;
            pn.ini(p);
            pnow=Bmut(Add(high,p),pn);
            temp=Add(temp,pnow,-1);
            ans[ans.length()-1]=p+'0';
            //cout<<"---"<<endl;
        }
        rec.ini(ans);
        return rec;
    }
    int main()
    {
        string a,b;
        while(cin>>a>>b)
        {
    
            numlist ax,bx;
            ax.ini(a);
            bx.ini(b);
            Bmut(Sqrt(ax),Sqrt(bx)).print();
            //Add(temp,-5);
        }
        return 0;
    }
  • 相关阅读:
    Redis on Spark:Task not serializable
    一次Spark应用程序参数优化案例
    Spark性能优化(2)——广播变量、本地缓存目录、RDD操作、数据倾斜
    Spark性能优化(1)——序列化、内存、并行度、数据存储格式、Shuffle
    Java – Convert IP address to Decimal Number
    Java IP地址字符串与BigInteger的转换, 支持IPv6
    Spark性能优化(2)——广播变量、本地缓存目录、RDD操作、数据倾斜
    Android Matrix类以及ColorMatri
    OpenGL中shader使用
    Android应用程序与SurfaceFlinger服务之间的共享UI元数据(SharedClient)的创建过程分析 .
  • 原文地址:https://www.cnblogs.com/LukeStepByStep/p/6387472.html
Copyright © 2020-2023  润新知