Week13必做部分

第一题

题目大意

给定两个数字,分别表示 n 和 k,并要求给出 k 个奇偶性相同的正整数,使得其和等于 n,例如 n = 10,k = 3,答案可以为 [4 2 4]。本题是SPJ

思路

这个题乍一看没有头绪,其实仔细想一下:题目只需要奇偶性相同就可以,试想,若一个数可以分成全是奇数的组合,则一定可以拆分为1+1+1+…+一个奇数;若全是偶数可以组成,则一定可以拆分为:2+2+2…+一个偶数。所以只需要判断这两种情况就可以了

代码
#include<bits/stdc++.h>
using namespace std;
int main(){
 int t=0;
 scanf("%d",&t);
 while(t--){
 long long n,k;
 scanf("%lld%lld",&n,&k);
 long long s=n-(k-1);
 long long m=n-(k-1)*2;
 if(s%2==1&&s>0){
  printf("YES\n");
  int i=0;
  for(;i<k-1;i++){
   if(i) printf(" ");
   printf("1");
  } 
  if(i) printf(" ");
  printf("%lld\n",s);
 }
 else if(m%2==0 && m>0){
  printf("YES\n");
  int i=0;
  for(;i<k-1;i++){
   if(i) printf(" ");
   printf("2");
  } 
  if(i) printf(" ");
  printf("%lld\n",m);
 }
 else printf("NO\n");
}
 return 0;
} 

第二题

题目大意

给定两个数字,分别表示 n 和 k,要求给出无法被 n 整除的第 k 大的正整数。例如 n = 3,k = 7,则前 7 个无法被 n 整除的正整数为 [1 2 4 5 7 8 10],所以第7个为 10。

思路

这个题实际要求的是:无法被 n 整除 n的倍数 ,只需要想到,无法被n整除的数,一定分布在:m*n~(m+1)*n之间,其中m大于等于0。所以,我们只需要先计算出k属于哪个区间内: k/(n-1), 再计算内部的偏移量:k%(n-1)。如果偏移量为0,则说明是上一个区间的最后一个数;若不为0,则为本区间的数。

代码
#include<bits/stdc++.h>
using namespace std;
//无法被 n 整除 n的倍数 
long long n,k;
int main(){
 int t;
 scanf("%d",&t);
 while(t--){
  scanf("%d%d",&n,&k);
  long long mod = k /(n-1);
  long long s=k%(n-1);
  if(s==0) printf("%lld\n",mod*n-1);
  else printf("%lld\n",mod*n+s);
 } 
  return 0;
}

第三题

题目大意

猫咪从天上往下掉,且只会掉在 [0, 10] 范围内,TT 初始站在位置五上,且每秒只能在移动不超过一米的范围内接住掉落的猫咪,如果没有接住,猫咪就会跑掉。例如,在刚开始的一秒内,TT 只能接到四、五、六这三个位置其中一个位置的猫咪。

在这里插入图片描述
输入给出不同时刻,猫咪的掉落位置,输出TT最大可获得的猫咪数量。

思路

首先,通过输入,得到不同时刻,每个点掉落的数量,并且获得掉落持续的总时间。之后,设定状态为 f [ k ] [ t ] f[k][t] f[k][t],即当TT在坐标为k的位置,时间是第t秒,可以获得的总数量。转移方程就是:从t-1时刻的3个位置,向k转移
f [ k ] [ t ] = m a x ( f [ k − 1 ] [ t − 1 ] , f [ k ] [ t − 1 ] , f [ k + 1 ] [ t − 1 ] ) + g [ k ] [ t ] f[k][t]=max(f[k-1][t-1],f[k][t-1],f[k+1][t-1])+g[k][t] f[k][t]=max(f[k1][t1],f[k][t1],f[k+1][t1])+g[k][t]
g [ k ] [ t ] g[k][t] g[k][t]是掉落的数量。

但要注意的是,因为t-1时刻下,k-1,k+1,k 并不是都可以来更新k位置,因为只有TT可能出现位置的左右一个单位之内,才可以转移状态,所以需要额外记录时刻t,位置k是否有效: v a l [ k ] [ t ] val[k][t] val[k][t],因此转移方程变为:

if(val[k-1][t-1]|val[k][t-1])|val[k+1][t-1])
   f[k][t]=max(f[k-1][t-1]*val[k-1][t-1],max(f[k][t-1]*val[k][t-1],f[k+1][t-1]*val[k+1][t-1]))+g[k][t];
 

最后,对t时刻的所有位置取max即可

代码
#include<cstdio>
#include<algorithm>
#include<cstring> 
using namespace std;
int g[15][100099];
int f[15][100099];
int val[15][100099]; //是否有效 
int main()
{
 int m;
 while(~scanf("%d",&m))
 {
  if(m==0) break;
  for(int s=0;s<=10;s++) f[s][0]=0;
  memset(val,0,sizeof 0);
  val[5][0]=1;
  memset(g,0,sizeof g);
  int a,b,maxt=0,ans=0;
  for(int i=0;i<m;i++){
   scanf("%d%d",&a,&b);
   maxt=max(maxt,b);
   g[a][b]++;
  } 
  for(int t=1;t<=maxt;t++){
   for(int k=0;k<=10;k++){
    int tmp=0;
    bool tag=0;
    if(k==0){
     tmp=max(f[0][t-1]*val[0][t-1],f[1][t-1]*val[1][t-1]);
     tag=val[0][t-1]|val[1][t-1];
    } 
    else if(k==10) {
     tmp=max(f[10][t-1]*val[10][t-1],f[9][t-1]*val[9][t-1]);
     tag = val[10][t-1]|val[9][t-1];
    }
    
    else  {
     tmp =max(f[k-1][t-1]*val[k-1][t-1],max(f[k][t-1]*val[k][t-1],f[k+1][t-1]*val[k+1][t-1]));
     tag =(val[k-1][t-1]|val[k][t-1])|val[k+1][t-1];
    }
    if(tag>0){
     val[k][t]=1;
     f[k][t]=tmp+g[k][t];
     ans = max(ans,f[k][t]); 
    }
    
   }
  }
  printf("%d\n",ans);
 }
 return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值