• 四平方和,激光炸弹


    四平方和(简单)

    在这里插入图片描述
    三层暴力遍历,再对最后一个数用平方求是否满足正整数的要求,有数据超时

    #include 
    #include 
    #include 
    using namespace std;
    
    const int N = 5e6;
    int n;
    int a[N];
    int main(){
        int a,b,c,d;
        scanf("%d",&n);
        for(int a = 0;a*a <= n;a++)
            for(int b = a;a*a+b*b <= n;b++)
                for(int c = b;a*a+b*b+c*c<= n;c++)
                    {
                        int t = n - a*a-b*b-c*c;
                        int d = sqrt(t);
                        if(d*d==t) //如果t可以表示为一个正整数的平方和
                        {
                            printf("%d %d %d %d",a,b,c,d);
                            return 0; 
                        }
                    }
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    在这里插入图片描述
    在这里插入图片描述

    1、使用哈希表记录c d两位的记录,c*c+d*d作为哈希表的下标,存储对应的c和d,并且只会保存一组且是第一组c*c+d*d
    2、将从0到n的cd组合都保存下来,再遍历0到n的ab组合,验证是否满足 n - a*a - b*b

    #include
    using namespace std;
    
    const int N = 1e5;
    typedef pair<int,int> pii;
    
    unordered_map<int,pii> mp;
    
    int main(){
        int n;
        scanf("%d",&n);
        for(int c = 0;c*c <= n;c++)
            for(int d = c; c*c+d*d <= n;d++)
                {   
                    int t = c*c+d*d;
                    if(mp.count(t) == 0)  mp[t] = {c,d};
                }
                
        for(int a = 0;a*a <= n;a++)
            for(int b = a;a*a+b*b <= n;b++)
            {
                int k = n - a*a - b*b;
                if(mp.count(k)) 
                {
                    printf("%d %d %d %d",a,b,mp[k].first,mp[k].second);
                    return 0;
                }
            }
            return 0 ;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30

    但是仍然超时
    在这里插入图片描述
    在这里插入图片描述

    最后AC的代码 其实和上面的原理一样 使用哈希表 但是不算c++内置的 哈希表 就没超时…

    #include
    #include
    using namespace std;
    const int N = 1e8 + 10;
    int h[N];
    int main() {
        int n;
        cin >> n;
        //打表,找出1 - n,所有完全平方数两两之和,如果存在只记第一次出现(题目要求找出字典序小的)
        for (int i = 0; i * i * 2<= n; i++) {
            for (int j = i; j * j + i * i <= n; j++) {
                if (!h[i * i + j * j])
                    h[i * i + j * j] = i + 1;//防止i = 0时在后面判断查找跳过 i = 0的情况
            }
        }
        //0<= a <= b <= c <= d,可以得出a^2 <= n / 4, a^2 + b^ 2 <= n / 2; 
        for (int i = 0; i * i * 4 <= n; i++) {
            for (int j = i; j * j + i * i <= n / 2; j++) {
                int t = n - i * i - j * j;
                if (h[t]) {
                    int c = h[t] - 1;   
                    //防止开根号后因为精度关系,向下取整,例:25 开根号得到4.99999向下取整为4;
                    int d = (sqrt(t - c * c) + 1e-4);
                    printf("%d %d %d %d", i, j, c, d);
                    return 0;
                }
            }
        }
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30

    在这里插入图片描述

    激光炸弹(简单)

    在这里插入图片描述
    边上的点不算,这种情况是四个点
    在这里插入图片描述
    这样有9个点
    在这里插入图片描述
    每个点的权值抽象成一个二维数组,然后求二维数组的前缀和,根据题目输入边长枚举每个满足边长的矩形的权值选出最大值

    如当边长为3时,可以有一个从1,1 到 3,3的 二维矩阵 计算权值
    在这里插入图片描述

    #include 
    #include 
    using namespace std;   
    
    const int N = 5010;
    int s[N][N];
    int n,r;
    int mx,my;
    int sum;
    
    int main(){
        scanf("%d%d",&n,&r);
        r = min(5001,r);// 5001即可包括整个打击范围
        mx = my = r;
        while(n--){
            int x,y,w;
            scanf("%d%d%d",&x,&y,&w);
            x++;y++;//为避免边界问题 从坐标开始1,1记录
            mx = max(x,mx);my = max(y,my);//记录坐标边界
            s[x][y] += w;//记录目标权值
        }
        //记录前缀和
        for(int i = 1;i <= mx;i++)
            for(int j = 1;j <= my;j++)
                s[i][j] += s[i-1][j]+s[i][j-1]-s[i-1][j-1];
    
    
        //从右下角坐标 枚举 边长为 r 的范围 计算 权重
        for(int i = r;i <= mx;i++)
            for(int j = r;j <= my ;j++)
                sum = max(sum,s[i][j] - s[i-r][j] - s[i][j-r] + s[i-r][j-r]);
    
        printf("%d\n",sum);
        
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36

    K倍区间(中等)

    在这里插入图片描述
    首先想到前缀和 然后暴力枚举 区间
    代码很简单 但是 不出所料的超时了 这里时间复杂度貌似是O(n2)?

    #include 
    
    const int N = 1e5+10;
    int a[N];
    int n,k;
    int sum;
    int main(){
        scanf("%d%d",&n,&k);
        for(int i = 1;i <= n;i++){
            scanf("%d",&a[i]);
            a[i] += a[i-1];
        }
        for(int i = 1;i<=n;i++)
            for(int j = i;j<=n;j++)
                 if((a[j] - a[j-i])%k == 0)
                    sum++;
        printf("%d",sum);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    在这里插入图片描述
    接下来就需要优化代码
    由前缀和可知 某个区间l - r的值等于 sum[r]- sum[l-1]
    ( sum[r] - sum[l-1])%k = 0
    可得 sum[r]%k == sum[l-1]%k
    则两种情况下 存在k 倍区间

    1. sum[r]%k == 0
    2. 某两段前缀和模k余数相同

    具体的做法就是开一个计数数组cnt[]cnt[i]就是计算余数为i的前缀和有多少个

    需要注意的是初始化 cnt[0] = 1 否则得不到正确结果

    因为:

    这里是用前缀和数组来算某个区间的和,前缀和数组s[0] = 0, s[i] = a[1] + a[2] + ... + a[i],如果想算a[L] + a[L + 1] + ... + a[R],它的值就等于s[R] - S[L - 1],所以当L = 1的时候,就会用到s[0]了

    cnt[0]存的是s[]中等于0的数的个数,由于s[0] = 0,所以最初等于0的有1个数,所以cnt[0] = 1

    #include 
    
    const int N = 1e5+10;
    typedef long long ll;
    ll a[N],cnt[N];
    int n,k;
    ll sum;
    int main(){
        scanf("%d%d",&n,&k);
        for(int i = 1;i <= n;i++){
            scanf("%d",&a[i]);
            a[i] += a[i-1];
        }
        cnt[0]++;//cnt[] 保存的是a[]%k中值为0的个数  初始时 a[0] = 0(前缀和数组的下标0没有用到) 所以初始有一个
        for(int i = 1;i<=n;i++)
            {
                sum += cnt[a[i]%k];  //统计与当前值求余相同的数量
                cnt[a[i]%k]++;       // 当前值模k的数量+1
            }
        printf("%lld",sum);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    在这里插入图片描述

    买不到的数目(简单)

    在这里插入图片描述
    数论
    裴蜀定理:对任何整数a,b和它们的最大公约数d,关于未知数x和y的线性不定方程(称为裴蜀等式):若a,b是整数,且(a,b)=d,那么对于任意的整数x,y,ax+by都一定是d的倍数,特别地,一定存在整数x,y,使ax+by=d成立
    它的一个重要推论是:a,b互质的充要条件是存在整数x,y使ax+by=1.

    可以推出一个数学公式,两个互质的数 最大不能组合出的数字为 (q-1)*p-q)

    #include
    using namespace std;
    
    int p,q;
    
    int main()
    {
        scanf("%d%d",&p,&q);
        printf("%d\n",(q-1)*p-q);
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    摘花生(简单)

    #include 
    
    using namespace std;
    
    const int N = 110;
    int peanut[N][N],peanuts[N][N];
    int t;
    int main(){
        cin>>t;
        while(t--){
            int r,c;
            cin >> r >> c;
            for(int i = 1 ;i <= r; i++)
                for(int j = 1 ;j <= c ; j++)
                    cin >> peanut[i][j];
            
            for(int i = 1;i <= r ; i++)
                for(int j = 1;j <= c ;j++)
                    peanuts[i][j] = max(peanuts[i-1][j],peanuts[i][j-1])+peanut[i][j];
                    
            cout << peanuts [r][c] <<endl;
        }
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
  • 相关阅读:
    双基证券:游戏版号发放整体趋势的向好将持续优化供给端
    【虚拟机】VMWare的NAT静态IP设置
    什么是域名?如何注册域名?
    vmware16.2内部win7联网
    windows查看并关闭端口对应进程占用的命令
    设置远程服务器共享本地磁盘
    了解 Android Kotlin 中 DataStore 的基本概念以及为什么应该停止在 Android 中使用 SharedPreferences
    卷王问卷考试系统SurveyKing,开源调查问卷和考试系统源码
    手把手教你做智能合约开源|多文件合约开源|引用文件开源
    防止SQL注入的四种方案
  • 原文地址:https://blog.csdn.net/weixin_56462041/article/details/123075251