当前位置:网站首页>四平方和,激光炸弹
四平方和,激光炸弹
2022-08-04 14:06:00 【之墨_】
四平方和(简单)

三层暴力遍历,再对最后一个数用平方求是否满足正整数的要求,有数据超时
#include <iostream>
#include <stdio.h>
#include <cmath>
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、使用哈希表记录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<bits/stdc++.h>
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 ;
}
但是仍然超时

最后AC的代码 其实和上面的原理一样 使用哈希表 但是不算c++内置的 哈希表 就没超时…
#include<iostream>
#include<cmath>
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;
}

激光炸弹(简单)

边上的点不算,这种情况是四个点
这样有9个点
每个点的权值抽象成一个二维数组,然后求二维数组的前缀和,根据题目输入边长枚举每个满足边长的矩形的权值选出最大值
如当边长为3时,可以有一个从1,1 到 3,3的 二维矩阵 计算权值
#include <stdio.h>
#include <algorithm>
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;
}
K倍区间(中等)

首先想到前缀和 然后暴力枚举 区间
代码很简单 但是 不出所料的超时了 这里时间复杂度貌似是O(n2)?
#include <stdio.h>
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);
}

接下来就需要优化代码
由前缀和可知 某个区间l - r的值等于 sum[r]- sum[l-1]
则( sum[r] - sum[l-1])%k = 0
可得 sum[r]%k == sum[l-1]%k
则两种情况下 存在k 倍区间
- sum[r]%k == 0
- 某两段前缀和模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 <stdio.h>
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);
}

买不到的数目(简单)

数论
裴蜀定理:对任何整数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<iostream>
using namespace std;
int p,q;
int main()
{
scanf("%d%d",&p,&q);
printf("%d\n",(q-1)*p-q);
return 0;
}
摘花生(简单)
#include <bits/stdc++.h>
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;
}
边栏推荐
猜你喜欢

MPLS experiment

nVisual二次开发——第二章 nVisual API操作指南Swagger使用

The Internet of things application development trend

七夕邂逅爱,那人一定在

南瓜科学产品升级 开启益智探索新篇章

九州云出席领航者线上论坛,共话5G MEC边缘计算现状、挑战和未来

State security organs conduct criminal arrest and summons review on Yang Zhiyuan, a suspect suspected of endangering national security

职场漫谈:为什么越是内卷的行业越有人争着抢着往里冲?好奇怪的说...

第六届未来网络发展大会,即将开幕!

Rust 从入门到精通04-变量
随机推荐
[LeetCode] 38. Appearance sequence
关于redis的几件小事(五)redis保证高并发以及高可用
"C pitfalls and pitfalls" reading summary
C# 复制列表
ACL 2022 | 社会科学理论驱动的言论建模
浙江大学团队使用基于知识图谱的新方法,从空间分辨转录组数据中推断细胞间通信状况
Button control switch 4017 digital circuit chip
Win11勒索软件防护怎么打开?Win11安全中心勒索软件防护如何设置
LCP 06. 拿硬币-遍历
人像分割技术解析与应用
router---dynamic route matching
第四讲 SVN
1375. 二进制字符串前缀一致的次数-前序遍历法
[UML] Summary of Information System Analysis and Design Knowledge Points
Analysis and application of portrait segmentation technology
砺夏行动|九州云章津楠:开源不是少数人的运动,大众化才是源泉
自监督学习未来是掩码自编码器?KAIST最新《自监督学习掩码自编码器》研究进展
PAT甲级:1038 Recover the Smallest Number
Rust from entry to proficient 04-variables
烂大街的缓存穿透、缓存击穿和缓存雪崩,你真的懂了?