题解
题目所说的概率可以直接通过m/n得到,也就是求m/n的第k1~k2位小数。不过因为k1,k2过大无法直接模拟。
最开始想的循环节处理,发现随着n的增大循环节也变大,无法直接通过循环节取模输出。
在模拟除法的过程中每次将m=m*10,m/n得到当前小数位,m=m%10。即每个小数位都会m=m*10%n。
m=m*10^(k1-1)%n在不爆精度的情况下就可以得到第k1位所用的m。根据同余定理可以将10^(k1-1)用快速幂求出再*m取模。
从k1到k2位使用模拟除法求出即可。
AC代码
#include <stdio.h>
#include <bits/stdc++.h>
#define fst first
#define sed second
using namespace std;
typedef long long ll;
const int INF = 0x3f3f3f3f;
const ll LINF = 0x3f3f3f3f3f3f3f3f;
ll m, n, k1, k2;
ll qpow(ll a, ll b)
{
ll res = 1;
while (b)
{
if (b & 1)
res = res * a % n;
a = a * a % n;
b >>= 1;
}
return res;
}
int main()
{
#ifdef LOCAL
freopen("C:/input.txt", "r", stdin);
#endif
int T;
cin >> T;
while (T--)
{
cin >> m >> n >> k1 >> k2;
m = m * qpow(10, k1 - 1) % n; //得到求出第k1-1位时的m
for (int i = k1; i <= k2; ++i)
{
m = m * 10;
putchar('0' + m / n);
m %= n;
}
cout << endl;
}
return 0;
}