目录
问题一:2327. 知道秘密的人数
问题描述:
在第 1 天,有一个人发现了一个秘密。
给你一个整数 delay ,表示每个人会在发现秘密后的 delay 天之后,每天 给一个新的人 分享 秘密。同时给你一个整数 forget ,表示每个人在发现秘密 forget 天之后会 忘记 这个秘密。一个人 不能 在忘记秘密那一天及之后的日子里分享秘密。
给你一个整数 n ,请你返回在第 n 天结束时,知道秘密的人数。由于答案可能会很大,请你将结果对 10^9 + 7 取余 后返回。
问题思路:
题目中的人数分为三个部分:①已经知道秘密,同时也可以分享秘密的人数(cnt_A)
②已经知道秘密,但是还不能分享秘密的人数(cnt_B)
③已经遗忘掉秘密,不计入最后的结果的人数(cnt_C)
一开始自己的思路是先假设所有人都不会忘记,直接计算知道秘密的人数(cnt_A+cnt_B)最后减去遗忘秘密的人数(cnt_C),发现处理遗忘秘密人数不太好操作,所以看着题解修正了自己的思路。
大概思路如下:
建立数组f[n]用来存储从1-n每天的第一类人的人数(即cnt_A).
建立i 从0到n的循环,先判断i+delay是否大于n,如果大于,则意味着此时知道秘密,但不能分享的第二类人数由当前的cnt_A与cnt_B组成(cnt_b = (cnt_b + f[i]),即可以分享秘密的人已经没有时间分享秘密了。
接着在[i+delay, i+forget]这个区间内,计算f[]的值(注意i+forget不要越界)
题目所要求的结果即变成:f[n-1]+cnt_B。
代码:
int peopleAwareOfSecret(int n, int delay, int forget){
int M = pow(10, 9)+7;
int f[1010];
memset(f,0,sizeof(int) * 1010);
f[0] = 1; //第一天有1个人知道
int cnt_b = 0;
for(int i=0; i<n; i++)
{
if(i + delay >=n)
cnt_b = (cnt_b + f[i]) % M;
for(int j= i+delay; j< fmin(i+forget,n); j++) //在[i+delay, i+forget]这个区间内更
新A类人数
f[j] = (f[j]+f[i]) %M;
}
return (f[n-1] + cnt_b) % M;
}