题解:AtCoder Beginner Contest 262D - I Hate Non-integer Number

题解:AtCoder Beginner Contest 262

D - I Hate Non-integer Number

·难度

普及/提高-

·题目

链接:D - I Hate Non-integer Number (atcoder.jp)

·思路

首先遍历一遍,一共取多少个数,之后每轮做一次dp,用f[j][k][l]表示考虑前j个数取其中k个并且该k个数的和除以i余l。其中我们依次枚举j、k、l,对于f[j][k][l]都可以用两种方式来求值(就是把这两种情况的f加起来):

①不选第j个数。用f[j-1][k][l](相当于只考虑前j-1个数,其他不变)更新。

②选择第j个数。用f[j-1][k-1][(l+i-a[j]%i)%i](这个比较复杂,是指考虑前j-1个数选k-1个【留出一个数给第j个数】,其中(l+i-a[j]%i)%i表示取第j个数之前除以i的余数就相当于刚刚取完第j个数除以i的余数把第j个数除以i的余数减去,需要注意的是减完之后可能是负数,所以要加上i)更新。

对于每一次遍历i,最终把答案加上f[n][i][0]

时间复杂度O(n4)

·代码

链接:Submission #42274509 - AtCoder Beginner Contest 262

#include<bits/stdc++.h>
#define N 110
#define P 998244353LL
using namespace std;
long long f[N][N][N]={},ans=0;
//其实用int也行,但是用longlong更稳妥
int a[N]={},n=0;
int main(){
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
        scanf("%d",&a[i]);
    }
    //输入
    for(int i=1;i<=n;i++){
        memset(f,0,sizeof(f));
        //初始化f
        f[0][0][0]=1;
        //需要注意考虑前0个数取0个求和除以i余0(和本身就是0)有一种情况
        for(int j=1;j<=n;j++){
            //最多有n个数
            for(int k=0;k<=j&&k<=i;k++){
                //一共只考虑前j个数,不肯能出现第大于j个数,而且这轮dp不会出现取大于i个数
                for(int l=0;l<i;l++){
                    f[j][k][l]=(f[j][k][l]+f[j-1][k][l])%P;
                    //第一种更新,注意要取模
                    if(k!=0){
                        f[j][k][l]=(f[j][k][l]+f[j-1][k-1][(l+i-a[j]%i)%i])%P;
                        //第二轮更新,除了取模还要注意“k-1”在k==0时是-1,所以会出现一些奇怪的问题
                    }
                }
            }
        }
        ans=(ans+f[n][i][0])%P;
        //更新答案也要取模
    }
    printf("%lld\n",ans);
    //打印答案
    return 0;
}

·注意

①注意答案一定要取模(否则longlong也不行),而且必须每次操作取一次模,否则还没跑完就炸了。

②做第二种转移时一定要判断k是否为0,是0不用做也不能做(参见我坎坷的调试过程:Submission #42264726 - AtCoder Beginner Contest 262

③每轮dp记得把f初始化成0

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
AtCoder Beginner Contest 134 是一场 AtCoder 的入门级比赛,以下是每道题的简要题解: A - Dodecagon 题目描述:已知一个正十二边形的边长,求它的面积。 解题思路:正十二边形的内角为 $150^\circ$,因此可以将正十二边形拆分为 12 个等腰三角形,通过三角形面积公式计算面积即可。 B - Golden Apple 题目描述:有 $N$ 个苹果和 $D$ 个盘子,每个盘子最多可以装下 $2D+1$ 个苹果,求最少需要多少个盘子才能装下所有的苹果。 解题思路:每个盘子最多可以装下 $2D+1$ 个苹果,因此可以将苹果平均分配到每个盘子中,可以得到最少需要 $\lceil \frac{N}{2D+1} \rceil$ 个盘子。 C - Exception Handling 题目描述:给定一个长度为 $N$ 的整数序列 $a$,求除了第 $i$ 个数以外的最大值。 解题思路:可以使用两个变量 $m_1$ 和 $m_2$ 分别记录最大值和次大值。遍历整个序列,当当前数不是第 $i$ 个数时,更新最大值和次大值。因此,最后的结果应该是 $m_1$ 或 $m_2$ 中较小的一个。 D - Preparing Boxes 题目描述:有 $N$ 个盒子和 $M$ 个物品,第 $i$ 个盒子可以放入 $a_i$ 个物品,每个物品只能放在一个盒子中。现在需要将所有的物品放入盒子中,每次操作可以将一个盒子内的物品全部取出并分配到其他盒子中,求最少需要多少次操作才能完成任务。 解题思路:首先可以计算出所有盒子中物品的总数 $S$,然后判断是否存在一个盒子的物品数量大于 $\lceil \frac{S}{2} \rceil$,如果存在,则无法完成任务。否则,可以用贪心的思想,每次从物品数量最多的盒子中取出一个物品,放入物品数量最少的盒子中。因为每次操作都会使得物品数量最多的盒子的物品数量减少,而物品数量最少的盒子的物品数量不变或增加,因此这种贪心策略可以保证最少需要的操作次数最小。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值