zoukankan      html  css  js  c++  java
  • C. Molly's Chemicals

    题目链接:http://codeforces.com/problemset/problem/776/C

    C. Molly's Chemicals
    time limit per test
    2.5 seconds
    memory limit per test
    512 megabytes
    input
    standard input
    output
    standard output

    Molly Hooper has n different kinds of chemicals arranged in a line. Each of the chemicals has an affection value, The i-th of them has affection value ai.

    Molly wants Sherlock to fall in love with her. She intends to do this by mixing a contiguous segment of chemicals together to make a love potion with total affection value as a non-negative integer power of k. Total affection value of a continuous segment of chemicals is the sum of affection values of each chemical in that segment.

    Help her to do so in finding the total number of such segments.

    Input

    The first line of input contains two integers, n and k, the number of chemicals and the number, such that the total affection value is a non-negative power of this number k. (1 ≤ n ≤ 105, 1 ≤ |k| ≤ 10).

    Next line contains n integers a1, a2, ..., an ( - 109 ≤ ai ≤ 109) — affection values of chemicals.

    Output

    Output a single integer — the number of valid segments.

    Examples
    input
    Copy
    4 2
    2 2 2 2
    output
    Copy
    8
    input
    Copy
    4 -3
    3 -6 -3 12
    output
    Copy
    3
    Note

    Do keep in mind that k0 = 1.

    In the first sample, Molly can get following different affection values:

    • 2: segments [1, 1], [2, 2], [3, 3], [4, 4];
    • 4: segments [1, 2], [2, 3], [3, 4];
    • 6: segments [1, 3], [2, 4];
    • 8: segments [1, 4].

    Out of these, 2, 4 and 8 are powers of k = 2. Therefore, the answer is 8.

    In the second sample, Molly can choose segments [1, 2], [3, 3], [3, 4].

    题目大意:给出n个数,和一个数k,现在问你有多少个区间和等于k的x次方,x从0到无穷

    思路:首先想到暴力算,遍历每个区间,但是看一下N的范围,显然行不通,那么仔细想一下题目要我们求什么:

    求某个区间和是否是某个数的K倍  也就是说sum[r]-sum[l]=pow(K,X)   分析一下这个公式:也许你第一眼看到觉得这样的话 你还不是要N*N的复杂度,一样行不通啊

    是的 这样看起来的确行不通,l 和 r 的取值范围是N  那么X呢?   数据最大只有10^14   那么就算K=2    2^X=1e14   不用我说  也知道X很小了吧  这就是这道题入手的关键了

    总共就三个  我们遍历其中两个  另外一个是不是就出来了呢?    显然 是的

    当然  r>l  这是必须的     所以我们不能把公式变为sum[r]=sum[l]+pow(K,X)   为什么呢?  因为我们要快速找到sum[r]这个值出现了几次  这样的话我们就判断不了这个值是在l之前出现的

    还是在 l 之后出现的 。  所以我们把公式变为  sum[l]=sum[r]-pow(K,X)   这样我们刚开始不用存下所有的sum值   存sum[r]的同时存下sum[l]   这样会就保证了sum[l]  在sum[r]前面了

    不知读者是否理解了  不理解的话  自己不妨试一下两种公式 自然会明白

    本题还有一个坑点  就是K=-1或者1 的时候  所以我们要用set 来存储 排除pow相等的情况  防止多算了次数

    看代码:

    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<map>
    #include<set>
    using namespace std;
    typedef long long LL;
    const int maxn=1e5+50;
    const LL INF=1e14+50;
    LL a[maxn];
    LL sum[maxn];
    map<LL,LL> m;
    set<LL>p;
    set<LL>::iterator it;
    int main()
    {
        int N,K;
    
        scanf("%d%d",&N,&K);
        for(int i=1;i<=N;i++)
        {
            scanf("%lld",&sum[i]);
            sum[i]+=sum[i-1];
        }
        int D=60;
        LL f=1;
        for(int i=1;i<=D;i++)
        {
            p.insert(f);
            f*=K;
            if(f>INF) break;
        }
        m[0]=1;
        LL ans=0;
        for(int i=1;i<=N;i++)
        {
            for(it=p.begin();it!=p.end();it++)
            {
                LL tmp=sum[i]-(*it);
                ans+=m[tmp];
    
            }
            m[sum[i]]++;
        }
        cout<<ans<<endl;
        return 0;
    }
    当初的梦想实现了吗,事到如今只好放弃吗~
  • 相关阅读:
    C# extern关键字的用法
    C#自定义集合类(二)
    C#自定义集合类(一)
    LINQ中交集、并集、差集、去重(十四)
    LINQ中转换操作符(十三)
    Oracle实现连乘和求和
    适配器模式
    HTTP网络协议与手写Web服务容器
    代理模式
    设计模式的几条家规
  • 原文地址:https://www.cnblogs.com/caijiaming/p/10610683.html
Copyright © 2011-2022 走看看