zoukankan      html  css  js  c++  java
  • [前缀和/数论] 数列

    【问题描述】
    给你一个长度为N的正整数序列,如果一个连续的子序列,子序列的和能够被K整除,那么就视此子序列合法,求原序列包括多少个合法的连续子序列?
    对于一个长度为8的序列,K=4的情况:2, 1, 2, 1, 1, 2, 1, 2 。它的答案为6,子序列是位置1->位置8,2->4,2->7,3->5,4->6,5->7。
    【输入格式】
    第一行:T,表示数据组数
    对于每组数据:
    第一行:2个数,K,N
    第二行:N个数,表示这个序列
    【输出格式】
    共T行,每行一个数表示答案
    【输入样例】
    2
    7 3
    1 2 3
    4 8
    2 1 2 1 1 2 1 2
    【输出样例】
    0
    6
    【数据规模】
    100%数据满足
    1<=T<=20
    1<=N<=50000
    1<=K<=1000000
    序列的每个数<=1000000000
    30%数据满足
    1<=T<=10
    1<=N,K<=1000

    #include<bits/stdc++.h>
    using namespace std;
    int a,tot,s[1000005];//s[i]用来存1~m前缀和 mod k余i的个数 
    int n,t,k;
    long long ans;
    int main()
    {freopen("seq.in","r",stdin);
     freopen("seq.out","w",stdout);
     scanf("%d",&t);
     for(int iii=1;iii<=t;iii++)
    {ans=0,tot=0;
     memset(s,0,sizeof(s));
     s[0]=1;
     scanf("%d%d",&k,&n);
     for(int i=1;i<=n;i++) {scanf("%d",&a);tot=(tot+a)%k;s[tot]++;}//计算s 
     for(int i=0;i<k;i++) if(s[i]) ans+=(s[i]*(s[i]-1)/2);
     //由于两个s[i]代表的i相减为0,两个对应位置间(左开右闭)的序列合法 
     //所以答案为每两个相同的s可确定一个合法答案,n个相同的s确定n*(n-1)/2个合法答案
     //最后把每个s[i]得出的答案相加就是总答案 
     printf("%lld
    ",ans);
    } 
    return 0;    
    }
  • 相关阅读:
    线性判别分析(Linear Discriminant Analysis, LDA)算法分析
    OpenCV学习(37) 人脸识别(2)
    OpenCV学习(36) 人脸识别(1)
    OpenCV学习(35) OpenCV中的PCA算法
    PCA的数学原理
    OpenCV学习(34) 点到轮廓的距离
    OpenCV学习(33) 轮廓的特征矩Moment
    OpenCV学习(32) 求轮廓的包围盒
    http://www.cnblogs.com/snake-hand/p/3206655.html
    C++11 lambda 表达式解析
  • 原文地址:https://www.cnblogs.com/Miniweasel/p/9844689.html
Copyright © 2011-2022 走看看