unittest
{
	assert( [ "3 2", "4 1 5" ].parse.expand.solve == 3 );
	assert( [ "13 17", "29 7 5 7 9 51 7 13 8 55 42 9 81" ].parse.expand.solve == 6 );
	assert( [
		"10 400000000",
		"1000000000 1000000000 1000000000 1000000000 1000000000 1000000000 1000000000 1000000000 1000000000 1000000000"
	].parse.expand.solve == 25 );
}



import std.algorithm;
import std.conv;
import std.functional;
import std.range;
import std.stdio;
import std.string;
import std.typecons;

void main()
{
	stdin.byLineCopy.parse.expand.solve.writeln;
}

auto parse( Range )( Range input )
if( isInputRange!Range && is( ElementType!Range == string ) )
{
	auto nm = input.front.split.to!( long[] );
	input.popFront;
	auto as = input.front.split.to!( long[] );
	return tuple( nm[ 1 ], as );
}

auto solve( long m, long[] as )
{
	// 累積和をMで割った余りの配列に変換
	auto c = 0L;
	foreach( ref a; as )
	{
		c += a;
		a = c % m;
	}
	
	// 「自分 - 自分より左にある余りが同じ値」でMの倍数の区間になるので、
	// 自分より左にある余りが同じ値の数をカウントすれば良い。
	auto ans = 0L;
	long[ long ] cs;
	cs[ 0 ]++;		// 余りが0のやつは自分のみの区間もMの倍数になるので加算しておく必要がある
	foreach( a; as )
	{
		if( a !in cs ) cs[ a ] = 0;
		ans += cs[ a ];
		cs[ a ]++;
	}
	
	return ans;
}
