二维数组前缀和
问题 C: 黑格覆盖
时间限制: 1 Sec 内存限制: 128 MB
[提交] [状态]
题目描述
在一张由 M * N 个小正方形格子组成的矩形纸张上,有 k 个格子被涂成了黑色。给你一张由 m * n 个同样小正方形组成的矩形卡片,请问该卡片最多能一次性覆盖多少个黑格子?
输入
输入共 k+1 行:
第 1 行为 5 个整数 M、N、m、n、k,其含义如题目所述。
接下来 k 行,每行 2 个整数,分别表示被涂成黑色的格子的行、列坐标。
输出
输出共 1 行,1 个整数,表示卡片一次性最多能覆盖的黑格子数。
样例输入 Copy
3 5 2 2
3
1 1
2 2
3 5
样例输出 Copy
2
对于 40%的数据:m=n;
对于 100%的数据:M、N、m、n、k 均小于等于 1000,所有黑格不重复出现。
这道题的坑:卡片有可能纸张大,所以要考虑循环结束的条件,卡片可以横着,也可以竖着
#include<bits/stdc++.h>
using namespace std;
int A[1010][1010];
int main()
{
int M,N,m,n,k;
scanf("%d %d %d %d %d",&M,&N,&m,&n,&k);
for(int i=1;i<=k;i++)
{
int a,b;
scanf("%d %d",&a,&b);
A[a][b]=1;
}
for(int i=1;i<=M;i++)
{
for(int j=1;j<=N;j++)
A[i][j]=A[i][j-1]+A[i-1][j]-A[i-1][j-1]+A[i][j];
}
int maxn=0;
if(m>M) m=M;
if(n>N) n=N;
for(int i=M;i>=m;i--)
{
for(int j=N;j>=n;j--)
{
int num=A[i][j]+A[i-m][j-n]-A[i-m][j]-A[i][j-n];
maxn=max(maxn,num);
}
}
if(m>N) m=N;
if(n>M) n=M;
for(int i=M;i>=n;i--)
{
for(int j=N;j>=m;j--)
{
int num=A[i][j]+A[i-n][j-m]-A[i-n][j]-A[i][j-m];
maxn=max(maxn,num);
}
}
printf("%d",maxn);
return 0;
}
排列组合dfs
问题 D: 找素数
时间限制: 1 Sec 内存限制: 128 MB
[提交] [状态]
题目描述
素数又称质数,是指一个大于 1 的正整数,如果除了 1 和它本身以外,不能再被其它的数整除, 例如:2、3、5、97 等都是素数。2 是最小的素数。
现在,给你 n 个数字,请你从中选取一部分,用它们拼出一个最大的素数。
注意:某个数字出现多少次你就可以用多少次,6 与 9 不能混用。
输入
输入共 2 行:
第 1 行,1 个整数 n,表示所给你的数字的个数。
第 2 行,n 个数字,用一个空格隔开,其含义如题目所述。
输出
输出共 1 行,1 个整数,为找到的最大素数。若无法拼出素数,输出-1。
样例输入 Copy
3 2 7 9
样例输出 Copy
97
提示
对于 30%的数据:n ≤ 3;
对于 60%的数据:n ≤ 4;
对于 100%的数据:n ≤ 5。
最开始用二进制那种做法(以前博客上有)结果不对。。除此之外,别无所知 ,看了别人的博客提示,豁然开朗
#include<bits/stdc++.h>
using namespace std;
int A[10],B[10],maxn=0,n;
int prime(int k)
{
if(k==0||k==1) return 0;
for(int i=2;i*i<=k;i++)
{
if(k%i==0) return 0;
}
return 1;
}
//找全排列
void fun(int len,int num)
{
if(prime(num)) maxn=max(maxn,num);
for(int i=1;i<=n;i++)
{
if(B[i]==0)
{
B[i]=1;
fun(len++,10*num+A[i]);
B[i]=0;
}
}
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%d",&A[i]);
fun(0,0);
if(maxn==0) maxn=-1;
printf("%d",maxn);
return 0;
}
南门的树的变式
问题 I: 序列 I
时间限制: 1 Sec 内存限制: 64 MB[提交] [状态] 题目描述 有一个整数序列,它的每个数各不相同,我们不知道它的长度是多少(即整数个数),但我们知道在某些区间中间至少有多少个整数,用区间(Li,Ri,Ci) 来描述,表示这个整数序列中至少有Ci个数来自区间[Li,Ri],给出若干个这样的区间,问这个整数序列的长度最少能为多少? 输入 第一行一个整数N,表示区间个数;接下来N行,每行三个整数(Li,Ri,Ci),描述一个区间。N<=1000,0<=Li<=Ri<=1000,1<=Ci<=Ri-Li+1 输出 仅一个数,表示该整数序列的最小长度。
样例输入
Copy 44 5 16 10 37 10 35 6 1
样例输出 Copy 4
第一遍是想的把最小的left和最大的right更新,就是不断的扩大区间范围,整体的思想是正确的,但是我忘了每个数据之间也是有限制的,满足大区间不一定满足小去见呀,突然有灵感了, 这个1000不是一个大数,于是,可以用南门的数那种做法呀,标记下标,先排序,再按照right排序,先将cnt分到左侧,再分到右侧,这样的点才更受用
#include<bits/stdc++.h>
using namespace std;
struct node
{
int l;
int r;
int cnt;
};
struct node a[1005];
int B[1005];
bool cmp(struct node x,struct node y)
{
return x.r<y.r;
}
int main()
{
int n;
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d %d %d",&a[i].l,&a[i].r,&a[i].cnt);
}
sort(a+1,a+1+n,cmp);//按右侧排序
for(int i=1;i<=n;i++)
{
int s=0;
for(int j=a[i].l;j<=a[i].r;j++)
{
if(B[j]==1)s++;
}
if(s>=a[i].cnt) continue;
else {
s=a[i].cnt-s;
}
for(int j=a[i].r;j>=a[i].l;j--)
{
if(B[j]==0)
{
B[j]=1;
s--;
}
if(s==0) break;
}
}
int sum=0;
for(int i=0;i<=a[n].r;i++)
if(B[i]) sum++;
printf("%d",sum);
return 0;
}
求共有区间
问题 M: Prison
时间限制: 1 Sec 内存限制: 128 MB
[提交] [状态]
题目描述
We have N ID cards, and there are M gates.
We can pass the i-th gate if we have one of the following ID cards: the Li-th, (Li+1)-th, …, and
Ri-th ID cards.
How many of the ID cards allow us to pass all the gates alone?
Constraints
·All values in input are integers.
·1≤N≤105
·1≤M≤105
·1≤Li≤Ri≤N
输入
Input is given from Standard Input in the following format:
N M
L1 R1
L2 R2
⋮
LM RM
输出
Print the number of ID cards that allow us to pass all the gates alone.
样例输入 Copy
4 2
1 3
2 4
样例输出 Copy
2
提示
Two ID cards allow us to pass all the gates alone, as follows:
·The first ID card does not allow us to pass the second gate.
·The second ID card allows us to pass all the gates.
·The third ID card allows us to pass all the gates.
·The fourth ID card does not allow us to pass the first gate.
此题本意就是求共有区间,不断更新Max_left和min_right,最后输出的时候注意下是否存在