A题 解题思路:
给出k , n, s, p 。 n 个人,
k个人,一个人需要 s 个纸飞机 ,一包纸里有 p 张纸,而且纸不能共享,求需要几包纸。s 和 p ,求出一个人需要几张纸,然后 * k ,最后再 / p 然后最后需要多少包纸。
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const long long M = 1e9 + 7;
const int N = 300;
typedef long long ll ;
int main(){
int k , n , s , p;
cin>>k>>n>>s>>p;
int res = 0;
if (n % s != 0){
res = n / s + 1;
}
else{
res = n / s;
}
res *= k;
int num = 0;
if (res % p != 0){
num = res / p + 1;
}
else{
num = res / p;
}
cout<<num<<endl;
return 0;
}
枚举做法,遍历所有点,求符合要求点的最大点,因此先按行遍历,让符合的点就 +1,然后按列遍历,让符合的再 +1,然后遍历所有的点,求出最大值。
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const long long M = 1e9 + 7;
const int N = 105;
typedef long long ll ;
char mp[N][N];
int ans[N][N];
int main(){
int k, n;
scanf("%d%d",&n,&k);
for (int i = 0; i < n; i++){
scanf("%s",mp[i]);
}
for (int i = 0; i < n; i ++){
int x = 0;
for (int j = k - 1; j < n; x++,j++){
int q = 0;
for (int p = x ; p <= j;p ++){
if (mp[i][p] == '#'){
q = 1;
break;
}
}
if (q == 0){
for (int p = x; p <= j; p++){
ans[i][p] += 1;
}
}
}
}
for (int i = 0; i < n; i++){
int x = 0;
for (int j = k - 1; j < n; x ++ , j ++){
int q = 0;
for (int p = x; p <= j; p ++){
if (mp[p][i] == '#'){
q = 1;
break;
}
}
if (q == 0){
for (int p = x; p <= j; p ++){
ans[p][i] += 1;
}
}
}
}
int mx = ans[0][0];
int xx = 1;
int yy = 1;
for (int i = 0; i < n; i++){
for (int j = 0; j < n; j++){
if (ans[i][j] > mx){
xx = i + 1;
yy = j + 1;
mx = ans[i][j];
}
}
}
printf("%d %d\n",xx,yy);
return 0;
}
数学公式,同时有些贪心。贪心就是第一个人多拿一次,其他的人少拿一次,也就是第一个人拿 i 次,其他人拿i - 1 次,k 个人 一次分 x 个,因此 推出公式: ( i - 1 ) * k * x + x <= n,这时要求 x 最大,因此 x <= n / ((i - 1) * k + 1), 然后我们可以遍历,从 1 到 d,这里的问题是
如果num = 0,直接break,因为 k * d 爆long long 了。
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const long long M = 1e9 + 7;
const int N = 300010;
typedef long long ll ;
int main(){
ll n , k, m , d;
scanf("%lld%lld%lld%lld",&n,&k,&m,&d);
ll mx = 0;
for (int i = 1; i <= d; i++){
ll num = n / ((i - 1) * k + 1);
if (num == 0) break;
num = min(num , m);
mx = max(mx,num * i);
}
printf("%lld",mx);
return 0;
}
超级思维题,利用前缀和,对于长 l 的窗口,我们不断向右移动,然后求出最大值,即最终的最大值
#include <map>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const long long M = 1e9 + 7;
const int N = 100010;
typedef long long ll ;
int ans[N];
int main(){
int l , w;
int res = 1e9;
scanf("%d%d",&w,&l);
for (int i = 1; i <= w - 1; i++){
scanf("%d",&ans[i]);
ans[i] += ans[i - 1];
}
for (int i = l; i < w; i ++){
res = min(res,ans[i] - ans[i - l]);
}
printf("%d\n",res);
return 0;
}