C语言程序设计100例之(58):连续子序列计数
例58 连续子序列计数
问题描述
给定一个正整数序列,对其和可被给定整数d整除的所有连续子序列进行计数。这些子序列可能重叠。例如,序列 2, 1, 2, 1, 1, 2, 1, 2包含6个连续的子序列,其总和可被4整除:6个子序列为:第一到第八个数、第二到第四个数、第二到第七个数、第三到第五个数、第四到第六个数和第五到第七个数。
输入
输入的第一行由一个整数c(1<=c<=200)组成,即测试用例的数量。
每个测试用例包括两行,第1行由两个整数d(1<=d<=1 000 000)和n(1<=n<=50 000)组成,分别是子序列和的除数d和序列长度。测试用例的第2行包含序列的n个元素,它们是介于1和1000000之间的整数。
输出
对于每个测试用例,输出连续子序列的和可被d整除的子序列个数。
输入样例
7 3
1 2 3
4 8
2 1 2 1 1 2 1 2
输出样例
(1)编程思路。
定义数组long long num[1000005]={0},其中数组num[i]保存前缀和除以d的余数为i的个数。
输入给定的n个整数时,一边输入,一边求出前缀和sum,再计算sum除以d的余数,对应的num[sum%d]元素值加1。余数为0的子序列一定能整除d。而余数相同的任意两个子序列相减,得到的子序列也一定能被d整除。
所以用循环遍历所有的余数个数(即num[0]~num[d-1]),将num[i] *(num[i]-1)/2的值累加起来(两两组合),再加上num[0]的值,就是所求的答案。
(2)源程序。
#include
#include
long long num[1000005];
int main()
{
int t;
scanf("%d",&t);
while (t--)
{
long long ans=0;
long long sum=0;
long long a;
memset(num,0,sizeof(num));
long long d,n;
scanf("%lld%lld",&d,&n);
int i;
for (i=1;i<=n;i++)
{
scanf("%lld",&a);
sum+=a;
sum%=d;
num[sum]++;
}
ans+=num[0];
for (i=0;i { if(!num[i]) continue; ans+=num[i]*(num[i]-1)/2; // 两两组合 } printf("%lld\n",ans); } return 0; } 题目描述 监狱有 n 个房间,每个房间关押一个犯人,有 m 种宗教,每个犯人会信仰其中一种。如果相邻房间的犯人的宗教相同,就可能发生越狱,求有多少种状态可能发生越狱。 输入格式 输入只有一行两个整数,分别代表宗教数 m(1≤m≤108) 和房间数 n(1≤n≤1012)。 输出格式 输出一行一个整数代表答案。答案对 100,003取模。 输入样例 2 3 输出样例 (1)编程思路。 n 个房间m 种宗教,每个房间犯人的宗教信仰选择都有m种,按乘法原理知总的排列数为mn,这么多情况进行排列看哪些情况可能越狱不是很方便。本题可以采用间接的方法,即可能发生越狱的方案数=总的排列数-不会越狱的方案数。 求不会越狱的方案数就比较简单了,第1个房间有m种宗教信仰选择,而后面的n-1个房间都有m-1种可能选择(由于必须满足同种宗教不相邻,因此第2个房间可选除了第1个房间已选之外的m-1种宗教信仰,第3个房间可选除了第2个房间已选之外的m-1种宗教信仰,…),由乘法原理知:不会越狱的方案数=m?(m?1)n?1 因此,可能发生越狱的方案数为: mn?m?(m?1)n?1 由于m和n数值较大,采用快速幂完成幂运算。 (2)源程序。 #include #define MOD 100003 long long quickPower(long long x,long long n) { long long p=1; while(n) { if (n%2==1) p=p*x%MOD; x=x*x%MOD; n=n/2; } return p; } int main() { long long n,m; scanf("%lld%lld",&m,&n); printf("%lld",(quickPower(m,n)-m*quickPower(m-1,n-1)%MOD+MOD)%MOD); return 0; } 问题描述 给定两个整数a和b,将a和b之间的数字(包括a和b)写在一个列表中。您的任务是计算列表中每个数字出现的次数。例如,a=1024,b=1032,则列表为 1024 1025 1026 1027 1028 1029 1030 1031 1032 列表中有10个0、10个1、7个2、3个3、4~9各1个。 输入习题58
58-1 越狱
58-2 数字计数