题解 | Big Integer-2019牛客暑期多校训练营第三场D题

题目来源于牛客竞赛:https://ac.nowcoder.com/acm/contest/discuss
题目描述:
For little pupils, a very large number usually means an integer with many many digits. Let’s define a class of big integers which consists only of the digit one(11⋯1). The first few integers in this class are 1,11,111,1111⋯. Denote A(n) as the n-th smallest integer in this class. To make it even larger, we consider integers in the form of A(ab) . Now, given a prime number p, how many pairs (i,j) are there such that 1≤i≤n, 1≤j≤m, A(ij)≡0(mod p).

输入描述:
The input contains multiple cases. The first line of the input contains a single integer T (1≤T≤100), the number of cases. For each case, the input consists of a single line, which contains 3 positive integers p,n,m (p,n,m≤109).

输出描述:
Print the answer, a single integer, in one separate line for each case.

示例1:
输入
2
11 8 1
7 6 2

输出
4
2

题解:
题解 | Big Integer-2019牛客暑期多校训练营第三场D题_第1张图片
题解 | Big Integer-2019牛客暑期多校训练营第三场D题_第2张图片
代码:

#include 
using namespace std;


typedef long long LL;

vector > plist;

int pow_mod(int x, int k, int p)
{
	int ret = 1;
	for (; k; k>>=1)
	{
		if (k&1) ret = 1LL*ret*x%p;
		x = 1LL*x*x%p;
	}
	return ret;
}

int f(int n, int k)
{
	int d = 1;
	for (auto pv: plist)
	{
	 	int t = (pv.second+k-1) / k;
	 	while (t--) d *= pv.first;
    }
	return n/d;
}

int main()
{
    int T, n, m, p, d, D;
	scanf("%d", &T);
	while (T--)
	{
		scanf("%d %d %d", &p, &n, &m);
		if (p == 2 || p == 5) {puts("0"); continue;}
		if (p == 3) // 10^d = 1 mod 27
		{
			//phi(27) = 18
			D = 18;
			p = 27;
		}
		else D = p-1;
		assert(pow_mod(10, D, p) == 1);
	  
		d = 1e9;
		for (int i = 1; i*i <= D; ++i)
		{
			if (D % i) continue;
			if (pow_mod(10, i, p) == 1)
			   d = min(d, i);
            if (pow_mod(10, D/i, p) == 1)
               d = min(d, D/i);
		}
		for (int i = 2; i*i <= d; ++i)
		{
		 	if (d % i) continue;
			int c = 0;
			while (d % i == 0) ++c, d /= i;
			plist.push_back(make_pair(i, c));	
		}
		if (d != 1) plist.push_back(make_pair(d, 1));
		LL ans = 0;
		for (int i = 1; i <= 30 && i <= m; ++i)
			ans += f(n, i);
		if (m > 30) ans += 1LL*(m-30)*f(n, 30);
		printf("%lld\n", ans);
		plist.clear();
	}
	return 0;
}

题目来源于牛客竞赛:https://ac.nowcoder.com/acm/contest/discuss

你可能感兴趣的:(题解)