K - PhD math (数学)题解

K. PhD math
time limit per test
8 seconds
memory limit per test
1024 megabytes
input
standard input
output
standard output

Johnny is a brilliant mathematics student. He loves mathematics since he was a child, now he is working on his PhD thesis. He faces a small mathematical problem, he has a n digit integer number (let us call it s) , he wants to find how many substring of s are divisible by a prime number p.

His supervisor professor is on vacation now, so can you play his role and help him with that?

Input

The first line contains the number of test cases T. Each of the next T lines represents a test case. For each test case you will be given 4 numbers: 1 ≤ a, b ≤ 1018, 1 ≤ n ≤ 106, 2 ≤ p < 200. Where a < b. s is not directly given in the input, you have to calculate it from a and b as follows: s is the first n digits from the decimal representation of a / b (treat a / b decimal representation as it has an infinite digits and just take the first n digits from the left)

Output

For each test case you should print one line containing the number of substrings of s that can be divided by p without remainder.

Examples
Input
Copy
3
2 4 3 5
2 4 2 5
2 4 1 5
Output
Copy
6
3
1
Note

For the first test case in the sample, a=2, b=4, n=3 and p=5. So s=500 and there are 6 substrings that are divided by p which are: 5, 0, 0, 50, 00, 500.

题意:给你两个数a,b,a/b得到一个小于1的数,这个小数的前n位组成一个字符串,求这个字符串有多少子串对一个质数P取模答案为0;
思路:注意到质数P的范围是\([1,200]\),因此我们可以利用这个质数范围,维护的集合是对于以i结尾的子串,有多少串取模答案为j注意到设一个以i-1为结尾的子串所代表的数字是t,则循环到i时该子串变为\(t*10 + arr[i]\)我们对他进行取模运算,就能得到答案,进一步思考可以得出,因为

t * 10 + arr[i] (mod p) = ((t%p)*(10%p))%p + arr[i]%p (mod p)

,这个式子说明对于每一个有相同余数的子串,在第i轮时余数相同所以我们只需要存储t%p,也就是说存储子串模p之后的数量,并且每次更新一下,就能得到最后答案

\(Coding:\)


#include<set>
#include<iostream>
#include<cstring>
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<map>
#include<algorithm>
#include<vector>
#include<queue>
#include<stack>
//#define ll long long
#define ull unsigned long long
#define pb push_back
#define mp make_pair
#define rep(i,a,b) for(int i=a;i<=b;++i)
#define bep(i,a,b) for(int i=a;i>=b;--i)
#define lowbit(x) (x&(-x))
#define ch() getchar()
#define pc(x) putchar(x)
#define ll long long 
using namespace std;

template<typename T>void read(T&x){
static char c;static int f;
for(c=ch(),f=1;c<'0'||c>'9';c=ch())if(c=='-')f=-f;
for(x=0;c>='0'&&c<='9';c=ch())x=x*10+(c&15);x*=f;
}
template<typename T>void write(T x){
static char q[65];int cnt=0;
if(x<0)pc('-'),x=-x;
q[++cnt]=x%10,x/=10;
while(x)
	q[++cnt]=x%10,x/=10;
while(cnt)pc(q[cnt--]+'0');
}
//#define int ull
//#define ll ull

const int N = 1e6+10;
int arr[N],n,p;
void doit(ll a,ll b){
	a*=10;
	rep(i,1,n){
		int k = a/b;
		arr[i] = k;
		a %= b;
		a *= 10;
	}
}
ll cnt[300],cnt2[300];
void solve(){
	int _;
	read(_);
	while(_--){
		memset(cnt,0,sizeof cnt);
		memset(cnt2,0,sizeof cnt2);
		ll a,b;
		read(a);read(b);read(n);read(p);
		doit(a,b);
		ll ans = 0;
		rep(i,1,n){
			//printf("%d\n",arr[i]);
			int z = arr[i];
			z%=p;
			int k = p-z;
			ll sum = 0;
			memset(cnt,0,sizeof cnt);
			rep(j,0,p-1){
				int v = ((j*10)%p+z%p)%p;
				//int c = (j*10)%p;
				//printf("%llu-%llu ",v,j);
				cnt[v] += cnt2[j];
				//cnt[v] += cnt2[c];
			}
			//pc('\n');
			//printf("%llu \n",z);
			cnt[z]++;
			sum = cnt[0];
			ans += sum;
			rep(j,0,p-1)cnt2[j] = cnt[j];
			//puts("");
		}
		//pc('\n');
		write(ans);pc('\n');
	}
}
signed main(){
	solve();
	return 0;
}

posted @ 2021-03-18 09:34  xiaodangao  阅读(62)  评论(0编辑  收藏  举报