zoukankan      html  css  js  c++  java
  • [蓝桥杯][2017年第八届真题]k倍区间

    暴力的做法是(O(n^2)),枚举左右端点(l)(r),通过前缀和计算出(sum[l sim r] = sum[r] - sum[l-1]),但不足以通过此题。

    题意可转化为:找两个端点(l)(r),使得(sum[l sim r]\%k = (sum[r] - sum[l-1])\%k == 0),即(sum[r] equiv sum[l-1] mod k)

    于是我们统计出所有(sum[i] mod k)的余数,记为(cnt[sum[i]\%k])

    最后枚举余数((0 sim k-1)),假设当前枚举的余数为(m),则满足(sum[l sim r]\%k == m)(l)(r)配对的个数为(C_{cnt[m]}^2)

    注意点

    由于(sum[0]=0),因此初始时(cnt[0]=1)

    const int N=1e5+10;
    LL sum[N],cnt[N];
    int n,k;
    
    int main()
    {
        cin>>n>>k;
    
        cnt[0]=1;
        for(int i=1;i<=n;i++)
        {
            cin>>sum[i];
            sum[i]+=sum[i-1];
            cnt[sum[i]%k]++;
        }
    
        LL ans=0;
        for(int i=0;i<k;i++)
        {
            ans+=cnt[i]*(cnt[i]-1)/2;
        }
            
        cout<<ans<<endl;
    
        //system("pause");
        return 0;
    }
    

    也可以采用下面更简洁的写法,不再是求组合数了,而是规定了一个顺序,每次求当前为右端点(r)的情况下,(1 sim i-1)中与(sum[r])同余模(k)的左端点(l)的个数。

    const int N=1e5+10;
    int sum[N],cnt[N];
    int n,k;
    
    int main()
    {
        cin>>n>>k;
    
        LL ans=0;
        cnt[0]=1;
        for(int i=1;i<=n;i++)
        {
            cin>>sum[i];
            sum[i]=(sum[i]+sum[i-1])%k;
            ans+=cnt[sum[i]];
            cnt[sum[i]]++;
        }
        cout<<ans<<endl;
    
        //system("pause");
        return 0;
    }
    
  • 相关阅读:
    WPF Get jiayuan outbox list(send mail box)
    Python中列表的各种方法
    Python中字符串拼接的三种方式
    Python2中input()、raw_input()和Python3中input()
    Python 中for...esle和while...else语法
    第 20 章 设置应用程序的样式并对其进行部署
    第 19 章 用户帐号
    第 18 章 Django 入门
    第 17 章 使用API
    安装requests
  • 原文地址:https://www.cnblogs.com/fxh0707/p/14561496.html
Copyright © 2011-2022 走看看