题解:P1664 每日打卡心情好

· · 题解

思路:模拟。用变量 n 记录下当前显示的连续天数,c 记录下当前连续不打卡的天数,ans 记录下最终的答案。

输入新的一天的打卡状态时,如果这天没有打卡,就将 c 自增 1 即可;如果这天打了卡,则需要先将 n 减去连续不打卡的惩罚 2^{c-1},将 c 清零(现在连续不打卡的天数为 0)并将 n 自增 1(今天打了卡),然后再计算今天增加的积分数。

如何快速计算出 2^{c-1} 呢?正常来讲有三种方法:pow(2,c-1)1<<c-1 和暴力计算。不过需要注意的是,在后两种方法中,2^{c-1} 本身可能爆 int(甚至 long long)。因此,需要先将 c-1 与一个数取 \min 再进行计算,下面代码中选取的是 25

另外注意 n 在减去 2^{c-1} 后可能变成负数,要和 0\max

#include<bits/stdc++.h>
using namespace std;
int main(){
    ios::sync_with_stdio(0);cin.tie(0);
    int s;cin>>s;
    int n=0,c=0;
    int ans=0; 
    bool a;
    while(s--){
        cin>>a;
        if(a){
            if(c)n=max(0,n-(1<<min(c-1,25)));
            c=0,n++;
            if(n>=1)ans++;
            if(n>=3)ans++;
            if(n>=7)ans++;
            if(n>=30)ans++;
            if(n>=120)ans++;
            if(n>=365)ans++;
        }else{
            c++;
        }
    }
    cout<<ans;
    return 0;
}