hdu 6794 Tokitsukaze and Multiple 前缀和思想+思维

题意:

t组输入,给你一个长度为n的数组,你每次可以从数组中找到a[i]和a[i+1],然后用a[i]+a[i+1]这个新元素来覆盖掉a[i]和a[i+1]的位置(1<=i<n),从而数组长度也减去1

你可以进行任意次这样的操作,输出最后的数组中有多少数,是p的倍数

 

题解:

给你一个a数组的前缀和数组w,我们保证a[i]>=1,前缀和w[i]都被p取余过

假设i<j,那么如果w[i]和w[j]相等,那也就是说(a[i+1]+a[i+2]+...+a[j])%p == 0,也就是说这一段是p的倍数

那么我们就可以依靠这一点去做题

 

我们先判断一下v[i]%p==0的点,然后依次这些点把原数组分割,分别对每一段进行上面这样的判断

 

代码:

#include <cstdio>
#include <algorithm>
#include <iostream>
#include <vector>
#include <map>
#include <queue>
#include <stack>
#include <set>
#include <ctime>
#include <cstring>
#include <cstdlib>
#include <math.h>
#include<map>
using namespace std;
typedef long long ll;
const int maxn = 3e5 + 5;
ll v[maxn];
map<ll,ll>r;
int main()
{
    ll t;
    scanf("%lld",&t);
    while(t--)
    {
        ll n,p;
        r.clear();
        scanf("%lld%lld",&n,&p);
//        ll vis[p+5];
//        memset(vis,0,sizeof(vis));
        for(ll i=1; i<=n; ++i)
            scanf("%lld",&v[i]),v[i]%=p;
        ll sum=0,mod=0;
        r[0]=1;
        for(ll i=1; i<=n; ++i)
        {
            if(v[i]==0)
            {
                mod=0;
                r.clear();
                sum++;
                r[0]=1;
            }
            else
            {
                mod=(mod+v[i])%p;
                r[mod]++;
                if(r[mod]>=2)
                {
                    mod=0;
                    sum++;
                    r.clear();
                }
                r[0]=1;
            }
        }
        printf("%lld\n",sum);
    }
    return 0;
}

 

posted @ 2020-08-02 13:14  kongbursi  阅读(137)  评论(0编辑  收藏  举报