|
|
|
|
package class_2022_07_1_week;
|
|
|
|
|
|
|
|
|
|
// 在第 1 天,有一个人发现了一个秘密。
|
|
|
|
|
// 给你一个整数 delay ,表示每个人会在发现秘密后的 delay 天之后,
|
|
|
|
|
// 每天 给一个新的人 分享 秘密。
|
|
|
|
|
// 同时给你一个整数 forget ,表示每个人在发现秘密 forget 天之后会 忘记 这个秘密。
|
|
|
|
|
// 一个人 不能 在忘记秘密那一天及之后的日子里分享秘密。
|
|
|
|
|
// 给你一个整数 n ,请你返回在第 n 天结束时,知道秘密的人数。
|
|
|
|
|
// 由于答案可能会很大,请你将结果对 109 + 7 取余 后返回。
|
|
|
|
|
// 测试链接 : https://leetcode.cn/problems/number-of-people-aware-of-a-secret/
|
|
|
|
|
public class Code03_NumberOfPeopleAwareOfASecret {
|
|
|
|
|
|
|
|
|
|
public static int peopleAwareOfSecret(int n, int delay, int forget) {
|
|
|
|
|
long mod = 1000000007;
|
|
|
|
|
// dpKnow[i], 第i天知道秘密的人
|
|
|
|
|
long[] dpKnow = new long[n + 1];
|
|
|
|
|
// dpForget[i], 第i天将要忘记秘密的人
|
|
|
|
|
long[] dpForget = new long[n + 1];
|
|
|
|
|
// dpShare[i], 第i天可以分享秘密的人
|
|
|
|
|
long[] dpShare = new long[n + 1];
|
|
|
|
|
// 第1天的时候,知道秘密的人1个,A
|
|
|
|
|
// 第1天的时候,将要忘记秘密的人0个
|
|
|
|
|
// 第1天的时候,可以分享秘密的人0个
|
|
|
|
|
dpKnow[1] = 1;
|
|
|
|
|
if (1 + forget <= n) {
|
|
|
|
|
dpForget[1 + forget] = 1;
|
|
|
|
|
}
|
|
|
|
|
if (1 + delay <= n) {
|
|
|
|
|
dpShare[1 + delay] = 1;
|
|
|
|
|
}
|
|
|
|
|
// 从第2天开始!i
|
|
|
|
|
for (int i = 2; i <= n; i++) {
|
|
|
|
|
// 第i天
|
|
|
|
|
// dpKnow[i - 1] - dpForget[i] + dpShare[i]
|
|
|
|
|
dpKnow[i] = (mod + dpKnow[i - 1] - dpForget[i] + dpShare[i]) % mod;
|
|
|
|
|
if (i + forget <= n) {
|
|
|
|
|
// dpShare[i] 是第i天,刚知道秘密的人!
|
|
|
|
|
// 这批人,会在i + forget天,都忘了!
|
|
|
|
|
dpForget[i + forget] = dpShare[i];
|
|
|
|
|
}
|
|
|
|
|
if (i + delay <= n) {
|
|
|
|
|
// dpShare[i + delay - 1] + dpShare[i] - dpForget[i + delay]
|
|
|
|
|
// i + delay 天 , 100天后,会分享秘密的人
|
|
|
|
|
// 第i天,有一些新人,i + delay天分享,一部分, dpShare[i]
|
|
|
|
|
// 第二部分呢?i + delay - 1天,知道秘密并且会散播的人,- dpForget[i + delay]
|
|
|
|
|
dpShare[i + delay] = (mod + dpShare[i + delay - 1] - dpForget[i + delay] + dpShare[i]) % mod;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return (int) dpKnow[n];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|