Polycarp and Div 3【Codeforces Round #496 (Div. 3)【D题】】【贪心】

题目链接:点击打开链接

 题目的意思是给你一串数字长度为(1~2e5),当然由于它的这一串数字是不打空格的输入,所以我用了string 定义了个字符串然后仅需要对字符串操作即可。题目要求得到的是:给你一串数组,你要找的是这串数组上能有多少段能被3整除的数,譬如3121,可以分成「3」、「1、2」、「1」,但最后的时候由于1不是3的倍数,所以ans=2;再举个有0的例子,100000可以分成「1」、「0」、「0」、「0」、「0」、「0」,ans=5,这里要考虑到的就是0也是3的倍数。

        思路:我们可以看到这样一个现状:

(一)、假如这个数可以被3整除,那么前面的数作废,开始判断后面的数

(二)、假如第一个数不能被三整除,那么考虑第二个数,若是不能被三整除,则看他们两个数的和,他们的与3分别的余数只有「1,1」、「1,2」、「2,2」这么三种情况,若是「1,2」到这就可以停下来,重新开始判断下一个了,否则无论是上述1、3情况下的哪一种都会被第三个一起给3整除掉,举个例子如果下一个数%3=1,遇上情况1,三个数和一定为三的倍数;情况2,第二个数和第三个数一定为三的倍数。所以每个式子长度不过三。

思路二:dp

用 dp[i]dp[i] 表示字符串前缀长度 ii 中最多可以分成多少个 33 的倍数。

这里我们考虑决策,有两种可能的决策:“不切”与“切”,也就是说要不要把这一位当做一个新的部分。

如果切的话,那么显而易见的 dp[i]=dp[i-1].dp[i]=dp[i1].

如果不切,我们要找到 max(j)_{1\leq j \leq i - 1}max(j)1ji1 使得 s[j...i]s[j...i] 当成数的话能被 33 整除。

我们由于 33 的整除性质,这段能被 33 整除当且仅当头尾两个数的前缀模 33 结果同余。

所以在线性 dpdp 的同时,记录一个 place[i]place[i] ,表示在当时前缀和模 33 等于 ii 的时候出现的最晚的位置。

所以我们在 dpdp 的时候,设 xx 为当前前缀和转成数字之后模 33 的值,所以得出方程 dp[i] = max(dp[i] , dp[place[x]] + 1);dp[i]=max(dp[i],dp[place[x]]+1); 然后顺带更新 placeplace 即可。

之后就可以直接 dpdp 了。


代码:

#include <iostream>
#include <algorithm>
#include <cmath>
#include <cstring>
using namespace std;

int main()
{
    ios::sync_with_stdio(false);
    string s;
    cin>>s;
    int sum=0;
    int cnt=0;
    int ans=0;
    for(int i=0;i<s.length();i++)
    {
        int k=s[i]-'0';
        sum+=k;
        cnt++;
        if(sum%3==0||cnt>=3||k%3==0)
        {
            ans++;
            cnt=0;
            sum=0;
        }
    }
    cout<<ans<<endl;
    return 0;
}
#include<bits/stdc++.h>

using namespace std;

const int MAXN = 200000 + 10;
int place[5] , N , dp[MAXN] , remain;
char s[MAXN];
int main(){
    scanf("%s" , s + 1);
    N = strlen(s + 1);

    memset(place , -1 , sizeof(place));
    dp[0] = 0;
    place[0] = 0;

    for(int i = 1;i <= N;i++){
        remain = (remain + s[i] - '0') % 3;
        dp[i] = dp[i - 1];
        if(place[remain] != -1) 
            dp[i] = max(dp[i] , dp[place[remain]] + 1);
        place[remain] = i;
    }

    cout << dp[N];
    return 0;
}



猜你喜欢

转载自blog.csdn.net/reallsp/article/details/81065336
今日推荐