基础数论专题题解集(暂未全部AC)
A - 青蛙的约会
题面
两只青蛙在网上相识了,它们聊得很开心,于是觉得很有必要见一面。它们很高兴地发现它们住在同一条纬度线上,于是它们约定各自朝西跳,直到碰面为止。可是它们出发之前忘记了一件很重要的事情,既没有问清楚对方的特征,也没有约定见面的具体位置。不过青蛙们都是很乐观的,它们觉得只要一直朝着某个方向跳下去,总能碰到对方的。但是除非这两只青蛙在同一时间跳到同一点上,不然是永远都不可能碰面的。为了帮助这两只乐观的青蛙,你被要求写一个程序来判断这两只青蛙是否能够碰面,会在什么时候碰面。
我们把这两只青蛙分别叫做青蛙A和青蛙B,并且规定纬度线上东经0度处为原点,由东往西为正方向,单位长度 米,这样我们就得到了一条首尾相接的数轴。设青蛙A的出发点坐标是 ,青蛙B的出发点坐标是 。青蛙A一次能跳 米,青蛙B一次能跳 米,两只青蛙跳一次所花费的时间相同。纬度线总长 米。现在要你求出它们跳了几次以后才会碰面。
题意
有一个总长为 的环形数轴,青蛙A从 出发,每次跳 米,青蛙B从 出发,每次跳 米,问最少跳多少次可以相遇(可能存在永远不相遇的情况)
输入格式 - Input
输入只包括 个整数,其中
输出格式 - Output
输出碰面所需要的跳跃次数,如果永远不可能碰面则输出一行"Impossible"
样例 - Sample
Input | Output |
---|---|
1 2 3 4 5 | 4 |
思路
由题意可得,设 A 和 B 的跳跃次数为 ,A 和 B 经过长度为 的环形数轴 或 次, 最终停在数字 上
可得 和
合并得
即
问题转化为求未知数为 和 的线性同余方程,由扩展欧几里得算法可得
,若 则方程有解,反之无解
由扩展欧几里得得出 后,
代码
Status | Time | Memory | Length | Lang |
---|---|---|---|---|
Accepted |
16ms | 368kB | 673 | G++ |
点击查看代码
#include <iostream>
using namespace std;
typedef long long ll;
inline ll exGCD(ll a, ll b, ll &x, ll &y)
{
if (!b)
{
x = 1, y = 0;
return a;
}
ll d = exGCD(b, a % b, x, y);
ll temp = x;
x = y;
y = temp - (a / b) * y;
return d;
}
int main()
{
#ifdef WatPz
string _fn = "A";
freopen((_fn + ".in").c_str(), "r", stdin);
freopen((_fn + ".out").c_str(), "w", stdout);
#endif
ll x, y, m, n, L, rx, ry;
cin >> x >> y >> m >> n >> L;
ll d = exGCD(n - m, L, rx, ry), t;
if ((y - x) % d == 0)
{
rx = rx * (x - y) / d;
t = L / d;
rx = (rx % t + t) % t;
cout << rx << endl;
}
else
{
cout << "Impossible" << endl;
}
return 0;
}
C - 荒岛野人
题面
克里特岛以野人群居而著称。岛上有排列成环行的 个山洞。这些山洞顺时针编号为 。
岛上住着 个野人,一开始依次住在山洞 中,以后每年,第 个野人会沿顺时针向前走 个洞住下来。每个野人 有一个寿命值 ,即生存的年数。下面四幅图描述了一个有 个山洞,住有 个野人的岛上前 年的情况。三个野人初始的洞穴编号依次为 ;每年要走过的洞穴数依次为 ;寿命值依次为 。
奇怪的是,虽然野人有很多,但没有任何两个野人在有生之年处在同一个山洞中,使得小岛一直保持和平与宁静,这让科学家们很是惊奇。他们想知道,至少有多少个山洞,才能维持岛上的和平呢?
题意
有很多野人,第 个野人初始位置为第 个山洞, 每年走 个山洞,寿命为
问你最少需要多少个山洞才能让野人两两不相遇
输入格式 - Input
第一行为一个整数 ,即野人的数目;
第二行到第 每行为三个整数 ,表示每个野人所住的初始洞穴编号,每年走过的洞穴数及寿命值。
输出格式 - Output
仅包含一个数 ,即最少可能的山洞数。输入数据保证有解,且 不大于 。
样例 - Sample
Input | Output |
---|---|
3 1 3 4 2 7 3 3 2 1 |
6 |
思路
对于两个野人 ,设经过 年后相遇,分别绕整个山洞群落 和 次,停在山洞
可得 和
即
根据 算出 的最小整数解后,若 则 相遇,反之不相遇
定义函数 判断 是否相遇,令
判断是否所有野人不会相遇:是则输出 ;否则 ,重复判断操作
(题目保证有解且 ,无须判断无解情况)
代码
Status | Time | Memory | Length | Lang |
---|---|---|---|---|
Accepted |
115ms | 364kB | 1208 | G++ (ISO C++20) -O2 64bit |
点击查看代码
#include <iostream>
using namespace std;
#define N 17
#define MAX(a,b) ((a) > (b) ? (a) : (b))
#define MIN(a,b) ((a) < (b) ? (a) : (b))
typedef long long ll;
ll n, c[N], p[N], l[N], maxc;
ll exGCD(ll a, ll b, ll &x, ll &y)
{
if (!b)
{
x = 1, y = 0;
return a;
}
ll d = exGCD(b, a % b, x, y);
ll t = x;
x = y;
y = t - (a / b) * y;
return d;
}
bool check(ll i, ll j, ll M)
{
ll x, y;
ll g = exGCD(p[j] - p[i], M, x, y);
if ((c[i] - c[j]) % g == 0)
{
x *= (c[i] - c[j]) / g;
y = M / g;
if (y < 0) y = -y;
x = (x % y + y) % y;
return x > MIN(l[i], l[j]);
}
else
return true;
}
bool allcheck(ll M)
{
for (ll i = 1; i <= n; i++)
{
for (ll j = i + 1; j <= n; j++)
{
if (!check(i, j, M))
{
return false;
}
}
}
return true;
}
signed main()
{
#ifdef WatPz
string _fn = "C";
freopen((_fn + ".in").c_str(), "r", stdin);
freopen((_fn + ".out").c_str(), "w", stdout);
#endif
scanf("%lld", &n);
maxc = 0;
for (ll i = 1; i <= n; i++)
{
scanf("%lld%lld%lld", &c[i], &p[i], &l[i]);
maxc = MAX(maxc, c[i]);
}
for (ll i = maxc; i <= 1000000; i++)
{
if (allcheck(i))
{
printf("%lld", i);
break;
}
}
return 0;
}
D - Bi-shoe and Phi-shoe
题面
Bamboo Pole-vault is a massively popular sport in Xzhiland. And Master Phi-shoe is a very popular coach for his success. He needs some bamboos for his students, so he asked his assistant Bi-Shoe to go to the market and buy them. Plenty of Bamboos of all possible integer lengths (yes!) are available in the market. According to Xzhila tradition,
Score of a bamboo = Φ (bamboo's length)
(Xzhilans are really fond of number theory). For your information, Φ (n) = numbers less than n which are relatively prime (having no common divisor other than 1) to n. So, score of a bamboo of length 9 is 6 as 1, 2, 4, 5, 7, 8 are relatively prime to 9.
The assistant Bi-shoe has to buy one bamboo for each student. As a twist, each pole-vault student of Phi-shoe has a lucky number. Bi-shoe wants to buy bamboos such that each of them gets a bamboo with a score greater than or equal to his/her lucky number. Bi-shoe wants to minimize the total amount of money spent for buying the bamboos. One unit of bamboo costs 1 Xukha. Help him.
题意
你要去给 个学生买竹子,第 个学生的幸运数字为 ,所需要的竹子长度为
需满足 (全部学生均满足 Φ(竹子长度) >= 幸运数字)
求 (就是竹子总长度)的最小值
输入格式 - Input
Input starts with an integer , denoting the number of test cases.
Each case starts with a line containing an integer denoting the number of students of Phi-shoe. The next line contains space separated integers denoting the lucky numbers for the students. Each lucky number will lie in the range .
第一行为 个数字 ,代表测试样例的数量
每个样例的第一行为 个数字 ,代表有 个学生
每个样例的第二行为 个数字:,为对应学生的幸运数字
输出格式 - Output
For each case, print the case number and the minimum possible money spent for buying the bamboos. See the samples for details.
对于每个测试样例,输出满足要求的最短竹子总长度(应符合样例的格式)
样例 - Sample
Input | Output |
---|---|
3 5 1 2 3 4 5 6 10 11 12 13 14 15 2 1 1 |
Case 1: 22 Xukha Case 2: 88 Xukha Case 3: 4 Xukha |
思路
对于数字
当 为素数时, 有
当 不为素数时,设 为小于 的最大素数,有
因此对于
当 为素数时,有
当 不为素数时,设 为大于 的最小素数,有
综上,使用素数筛法后,从尾到头预处理答案即可
代码
Status | Time | Memory | Length | Lang |
---|---|---|---|---|
Accepted |
142ms | 21008kB | 1028 | C++ 17 (g++ 7.5.0) |
点击查看代码
#include <iostream>
#include <algorithm>
using namespace std;
#define N 1000004
typedef long long ll;;
bool p[N + 2];
ll phi[N + 2];
ll cnt, prime[N + 2];
void Get_ol()
{
for (ll i = 2; i < N; i++)
{
if (!p[i])
{
prime[++cnt] = i;
phi[i] = i - 1;
}
for (ll j = 1; j <= cnt && i * prime[j] < N; j++)
{
p[i * prime[j]] = 1;
if (i % prime[j] == 0)
{
phi[i * prime[j]] = phi[i] * prime[j];
break;
}
phi[i * prime[j]] = phi[i] * phi[prime[j]];
}
}
}
ll _, n, a, ans[N + 2];
ll r_ans = 0;
int main()
{
#ifdef WatPz
string _fn = "D";
freopen((_fn + ".in").c_str(), "r", stdin);
freopen((_fn + ".out").c_str(), "w", stdout);
#endif
Get_ol();
ll k = prime[cnt];
for (ll i = k - 1; i >= 1; i--)
{
ans[i] = k;
if (!p[i]) k = i;
}
cin >> _;
for (ll __ = 1; __ <= _; __++)
{
cin >> n;
r_ans = 0;
for (ll i = 1; i <= n; i++)
{
cin >> a;
r_ans += ans[a];
}
printf("Case %lld: %lld Xukha\n", __, r_ans);
}
return 0;
}
H - Relatives
题面
Given , a positive integer, how many positive integers less than are relatively prime to ? Two integers and are relatively prime if there are no integers such that and .
题意
给定一个正整数 ,求
即求 范围在 内有多少正整数与 互质(最大公因数 为1)
输入格式 - Input
There are several test cases. For each test case, standard input contains a line with n <= 1,000,000,000. A line containing 0 follows the last case.
多组样例,每组样例包含 个正整数 或 ,后者代表样例结束
输出格式 - Output
For each test case there should be single line of output answering the question posed above.
对于每组样例,输出上面问题的答案
样例 - Sample
Input | Output |
---|---|
7 12 0 |
6 4 |
思路
题目的问题实际上是让你求:对于给定的 ,的值为多少
写一个欧拉函数即可解决
代码
Status | Time | Memory | Length | Lang |
---|---|---|---|---|
Accepted |
0ms | 328kB | 543 | G++ |
点击查看代码
#include <iostream>
using namespace std;
typedef long long ll;
ll phi(ll n)
{
ll res = n;
for (ll i = 2; i * i <= n; i++)
{
if (n % i == 0)
{
n /= i;
res = res - res / i;
}
while (n % i == 0)
n /= i;
}
if (n > 1)
res = res - res / n;
return res;
}
ll n;
int main()
{
#ifdef WatPz
string _fn = "H";
freopen((_fn + ".in").c_str(), "r", stdin);
freopen((_fn + ".out").c_str(), "w", stdout);
#endif
while (1)
{
scanf("%lld", &n);
if (!n) break;
printf("%lld\n", phi(n));
}
return 0;
}
I - GCD
题面
The greatest common divisor of two positive integers and , sometimes written , is the largest divisor common to and , For example, , .
can be easily found by the Euclidean algorithm. Now Carp is considering a little more difficult problem:
Given integers and , how many integer satisfies and .
题意
给你两个正整数 和 ,求
即求 范围在 内有多少正整数与 的 最大公约数 大于等于
输入格式 - Input
The first line of input is an integer representing the number of test cases. The following T lines each contains two numbers and , representing a test case.
第一行为 个整数 ,代表测试样例的数量
每个样例包含 个整数 和
输出格式 - Output
For each test case there should be single line of output answering the question posed above.
对于每组样例,输出上面问题的答案
样例 - Sample
Input | Output |
---|---|
3 1 1 10 2 10000 72 |
1 6 260 |
思路
不妨设 则可得 即 与 互素
由 可得 (即 为 的约数),
当 时, 满足该条件的 数量
综上,循环遍历 的所有约数,设其中大于等于 的数字为
令 即可
代码
Status | Time | Memory | Length | Lang |
---|---|---|---|---|
Accepted |
31ms | 1372kB | 755 | G++ |
点击查看代码
#include <iostream>
using namespace std;
typedef long long ll;
ll phi(ll n)
{
ll res = n;
for (ll i = 2; i * i <= n; i++)
{
if (n % i == 0)
{
n /= i;
res = res - res / i;
}
while (n % i == 0)
n /= i;
}
if (n > 1)
res = res - res / n;
return res;
}
ll _, n, m, ans;
int main()
{
#ifdef WatPz
string _fn = "I";
freopen((_fn + ".in").c_str(), "r", stdin);
freopen((_fn + ".out").c_str(), "w", stdout);
#endif
scanf("%lld", &_);
while (_--)
{
scanf("%lld%lld", &n, &m);
ans = 0;
for (ll p = 1; p * p <= n; p++)
{
if (n % p == 0)
{
if (p >= m)
ans += phi(n / p);
if (n / p >= m && p != n / p)
ans += phi(p);
}
}
printf("%lld\n", ans);
}
return 0;
}
J - Leading and Trailing
题面
You are given two integers: and , your task is to find the most significant three digits, and least significant three digits of .
题意
给出两个正整数 和 ,求 的前三位数字和后三位数字
输入格式 - Input
Input starts with an integer , denoting the number of test cases.
Each case starts with a line containing two integers: and .
第一行为 个整数 ,代表测试样例的数量
每个样例包含 个整数 和
输出格式 - Output
For each case, print the case number and the three leading digits (most significant) and three trailing digits (least significant). You can assume that the input is given such that contains at least six digits.
对于每组样例,输出 的前三位数字和后三位数字
样例 - Sample
Input | Output |
---|---|
5 123456 1 123456 2 2 31 2 32 29 8751919 |
Case 1: 123 456 Case 2: 152 936 Case 3: 214 648 Case 4: 429 296 Case 5: 665 669 |
思路
对于后三位数字,可以考虑使用 快速幂算法,将取模的 设为
对于前三位数字,设
可得
化简得
则:
归纳得:
前三位数字
(因为 的十位和百位可能出现 ,因此输出时需要输出 "%03lld" 而不是 "%lld")
代码
Status | Time | Memory | Length | Lang |
---|---|---|---|---|
Accepted |
5ms | 648kB | 699 | C++ 17 (g++ 7.5.0) |
点击查看代码
#include <iostream>
#include <cmath>
using namespace std;
#define isDigit(x) ('0' <= x && x <= '9')
typedef long long ll;
ll qpow(ll x, ll power, ll mod)
{
x %= mod;
ll res = 1;
for (; power; power >>= 1, (x *= x) %= mod)
{
if (power & 1)
(res *= x) %= mod;
}
return res;
}
ll _, n, k;
int main()
{
#ifdef WatPz
string _fn = "J";
freopen((_fn + ".in").c_str(), "r", stdin);
freopen((_fn + ".out").c_str(), "w", stdout);
#endif
scanf("%lld", &_);
for (ll __ = 1; __ <= _; __++)
{
scanf("%lld%lld", &n, &k);
double kp = 1.0 * k * log10(n);
kp -= (ll) kp;
printf("Case %lld: %lld %03lld\n", __, ll(pow(10, kp) * 100), qpow(n, k, 1000));
}
return 0;
}
K - Goldbach's Conjecture
题面
Goldbach's conjecture is one of the oldest unsolved problems in number theory and in all of mathematics.
It states:
Every even integer, greater than , can be expressed as the sum of two primes.
Your task is to check whether this conjecture holds for integers up to .
题意
给你一个数字 ( 为偶数),设素数集合为
请你求出存在多少组 满足 强哥德巴赫猜想(即 )
输入格式 - Input
Input starts with an integer , denoting the number of test cases.
Each case starts with a line containing an integer .
第一行为 个整数 ,代表测试样例的数量
每个样例包含 个整数 是偶数
输出格式 - Output
For each case, print the case number and the number of ways you can express n as sum of two primes. To be more specific, we want to find the number of (a, b) where:
- Both a and b are prime,
- a + b = n and
- a ≤ b.
对于每组样例,输出能够满足强哥德巴赫猜想的 数量(关于 的定义见上文)
样例 - Sample
Input | Output |
---|---|
2 6 4 |
Case 1: 1 Case 2: 1 |
思路
因为 强哥德巴赫猜想 现在数学界都没法完全证明,所以就别想着推什么通解了233
直接暴力循环所有质数就行 xD
代码
Status | Time | Memory | Length | Lang |
---|---|---|---|---|
Accepted |
592ms | 52240kB | 897 | C++ 17 (g++ 7.5.0) |
点击查看代码
#include <iostream>
using namespace std;
#define N 10000000
#define pp (9999991 >> 1)
bool p[N];
int phi[N];
int cnt, prime[664585];
void Get_ol()
{
for (int i = 2; i < N; i++)
{
if (!p[i])
{
prime[++cnt] = i;
phi[i] = i - 1;
}
for (int j = 1; j <= cnt && i * prime[j] < N; j++)
{
p[i * prime[j]] = 1;
if (i % prime[j] == 0)
{
phi[i * prime[j]] = phi[i] * prime[j];
break;
}
phi[i * prime[j]] = phi[i] * phi[prime[j]];
}
}
}
int _, a, tt;
int main()
{
#ifdef WatPz
string _fn = "K";
freopen((_fn + ".in").c_str(), "r", stdin);
freopen((_fn + ".out").c_str(), "w", stdout);
#endif
Get_ol();
scanf("%d", &_);
for (int __ = 1; __ <= _; __++)
{
scanf("%d", &a);
tt = 0;
for (int j = 1; prime[j] <= (a >> 1); j++)
{
if (!p[a - prime[j]])
tt++;
}
printf("Case %d: %d\n", __, tt);
}
return 0;
}
L - Harmonic Number (II)
题面
I was trying to solve problem N - Harmonic Number, I wrote the following code
long long H( int n ) {
long long res = 0;
for( int i = 1; i <= n; i++ )
res = res + n / i;
return res;
}
Yes, my error was that I was using the integer divisions only. However, you are given n, you have to find H(n) as in my code.
题意
这个憨憨把 看成了 ,并且在计算 的时候,用了整数类型
这意味着他将得到错误的答案
但是呢,如果每个分数都向下取整,求这个答案也很有意思,因此他打算让你解决这个问题
(因为他写的屎山代码实在是太慢了 xD)
输入格式 - Input
Input starts with an integer , denoting the number of test cases.
Each case starts with a line containing an integer .
第一行为 个整数 ,代表测试样例的数量
每个样例包含 个整数
输出格式 - Output
For each case, print the case number and calculated by the code.
对于每组样例,输出 的理论运行结果
样例 - Sample
Input | Output |
---|---|
11 1 2 3 4 5 6 7 8 9 10 2147483647 |
Case 1: 1 Case 2: 3 Case 3: 5 Case 4: 8 Case 5: 10 Case 6: 14 Case 7: 16 Case 8: 20 Case 9: 23 Case 10: 27 Case 11: 46475828386 |
思路
-
对于 向下取整 这种特殊操作,一般采取 定性分析 的方法
不妨设 ,则 -
通过数形结合的思维,不难发现 的几何意义:
长度为 的长块最多能够分成长度为 的长块的数量 -
因此对于 (),其代数定义为:
令 ,则有
(也就是说 代表的是 满足 的所有 中的最大值)因此满足 的 的数量,也就是 ,等价于
-
因此,我们只需要遍历 可以取到的所有值,根据 算出数量,再乘上当前的实际贡献 就行
-
但到这里还没有完全解决, 的最大值是 ,如果以 的复杂度做单组样例
还是会 TLE,因此继续考虑数形结合(做完了但是没完全做完)我们可以将 视为一个正方形的面积
当 时,所对应的 只能由 得到,且
当 时,所对应的 可由 或 其他数字 得到,且 -
因此可以考虑设 , 用 表示 时的 和 时 的
则
需要注意的是,对于求和公式中的任意 ,若 ,则只能计算一次
(别找抄公式啊喂(恼)) -
所以严谨的公式应该是:
代码
Status | Time | Memory | Length | Lang |
---|---|---|---|---|
Accepted |
1201ms | 1044kB | 667 | C++ 17 (g++ 7.5.0) |
点击查看代码
#include <iostream>
#include <cstring>
using namespace std;
typedef long long ll;
// sqrt(2147483647) = 46340
ll vis[46350];
ll solve(ll n)
{
memset(vis, 0, sizeof vis);
ll res = 0, p;
for (ll i = 1; i * i <= n; i++)
{
p = n / i, res += (n / p - (n / (p + 1))) * p;
if (n / i != i)
p = i, res += (n / p - (n / (p + 1))) * p;
}
return res;
}
ll _, a;
int main()
{
#ifdef WatPz
string _fn = "L";
freopen((_fn + ".in").c_str(), "r", stdin);
freopen((_fn + ".out").c_str(), "w", stdout);
#endif
scanf("%lld", &_);
for (ll __ = 1; __ <= _; __++)
{
scanf("%lld", &a);
printf("Case %lld: %lld\n", __, solve(a));
}
return 0;
}
N - Harmonic Number
题面
In mathematics, the harmonic number is the sum of the reciprocals of the first natural numbers:
In this problem, you are given , you have to find .
题意
如题,给你 ,求解
输入格式 - Input
Input starts with an integer , denoting the number of test cases.
Each case starts with a line containing an integer .
第一行为 个整数 ,代表测试样例的数量
每个样例包含 个整数
输出格式 - Output
For each case, print the case number and the nth harmonic number. Errors less than will be ignored.
对于每组样例,输出对应的 (精度误差 )
样例 - Sample
Input | Output |
---|---|
12 1 2 3 4 5 6 7 8 9 90000000 99999999 100000000 |
Case 1: 1 Case 2: 1.5 Case 3: 1.8333333333 Case 4: 2.0833333333 Case 5: 2.2833333333 Case 6: 2.450 Case 7: 2.5928571429 Case 8: 2.7178571429 Case 9: 2.8289682540 Case 10: 8.8925358988 Case 11: 18.9978964039 Case 12: 18.9978964139 |
思路
调和级数这种东西,欧拉给过一个公式,这个公式在 很大的时候误差很小
(其中 为 欧拉常量,)
因此可以选择小数据打表,大数据使用公式
但是!既然都要打表了,干嘛不直接从头到尾都打表(BDFS是什么√8)
真男人不用欧拉的公式,直接打表 xD
看下数据, 最大值为 ,直接存答案爆炸
可以先试一下 , 时的 clock
Windows 下实测发现是 ,因此单次最大查询存答案的思路可行
考虑到 的最大值是 ,假设每次询问的数字是均分的
(这样可以让平均复杂度接近实际复杂度)
那么 ,因此可以考虑每隔 个点记录一次答案
这样单次询问最多跑 个点, 最大询问最多跑 个点,相当于两次最大查询
题目限制是 ,,AC就完了!
(实际数据因为评测环境是 Linux,跑得反而更快,才 )
代码
Status | Time | Memory | Length | Lang |
---|---|---|---|---|
Accepted |
224ms | 772kB | 724 | C++ 17 (g++ 7.5.0) |
点击查看代码
#include <iostream>
using namespace std;
#define P 10000
double val[P + 10];
// n = 1e8, sec ~= 0.4
void solve()
{
double ans = 0.0;
int i, j, p;
for (i = 0; i <= P - 1; i++)
{
val[i] = ans;
for (j = 1; j <= P; j++)
{
p = i * P + j;
ans += 1.0 / p;
}
}
val[P] = ans;
}
int _, a;
double ans;
int main()
{
#ifdef WatPz
string _fn = "N";
freopen((_fn + ".in").c_str(), "r", stdin);
freopen((_fn + ".out").c_str(), "w", stdout);
#endif
solve();
scanf("%d", &_);
for (int __ = 1; __ <= _; __++)
{
scanf("%d", &a);
ans = val[a / P];
for (int i = (a - (a % P)) + 1; i <= a; i++)
{
ans += 1.0 / i;
}
printf("Case %d: %.10lf\n", __, ans);
}
return 0;
}
P - Large Division
题面
Given two integers, and , you should check whether is divisible by or not. We know that an integer is divisible by an integer if and only if there exists an integer such that .
题意
给你 和 ,判断 能否被 整除(即判断 )
输入格式 - Input
Input starts with an integer , denoting the number of test cases.
Each case starts with a line containing two integers and . Numbers will not contain any leading zeroes.
第一行为 个整数 ,代表测试样例的数量
每个样例包含 个整数 和
输出格式 - Output
For each case, print the case number first. Then print divisible if a is divisible by b. Otherwise print not divisible.
对于每组样例,若 则输出 divisible,否则输出 not divisible
样例 - Sample
Input | Output |
---|---|
6 101 101 0 67 -101 101 7678123668327637674887634 101 11010000000000000000 256 -202202202202000202202202 -101 |
Case 1: divisible Case 2: divisible Case 3: divisible Case 4: not divisible Case 5: divisible Case 6: divisible |
思路
看到第一眼,a % b == 0 解决
然后一看范围, 是个高精度数字,咋搞?
很简单,利用同余定理的性质
假设 ,则有
对于 ,可将其分解为十进制写法
其中 为范围在 的整数
这样的话不难看出, 的结果和 的结果相同
则只需将 按照高位到低位的顺序读入,然后每读入一位取模即可
因为 最大值能够达到 int 的极限,所以为了防止溢出应选择 long long
代码
Status | Time | Memory | Length | Lang |
---|---|---|---|---|
Accepted |
5ms | 660kB | 951 | C++ 17 (g++ 7.5.0) |
点击查看代码
#include <iostream>
using namespace std;
#define isDigit(x) ('0' <= x && x <= '9')
typedef long long ll;
ll _, __, len, a[220], b;
inline ll qreadStr()
{
ll len = 0; char ch = getchar();
while (!isDigit(ch))
ch = getchar();
while (isDigit(ch))
a[++len] = ch - '0', ch = getchar();
return len;
}
inline ll qread()
{
ll res = 0; char ch = getchar();
while (!isDigit(ch))
ch = getchar();
while (isDigit(ch))
res = (res << 3) + (res << 1) + ch - '0', ch = getchar();
return res;
}
int main()
{
#ifdef WatPz
string _fn = "P";
freopen((_fn + ".in").c_str(), "r", stdin);
freopen((_fn + ".out").c_str(), "w", stdout);
#endif
_ = qread();
for (__ = 1; __ <= _; __++)
{
len = qreadStr(), b = qread();
ll res = 0;
for (ll i = 1; i <= len; i++)
{
res = (res << 3) + (res << 1) + a[i];
res %= b;
}
printf("Case %d: ", __);
printf(res ? "not divisible\n" : "divisible\n");
}
return 0;
}
Q - Fantasy of a Summation
题面
If you think codes, eat codes then sometimes you may get stressed. In your dreams you may see huge codes, as I have seen once. Here is the code I saw in my dream.
#include <stdio.h>
int cases, caseno;
int n, K, MOD;
int A[1001];
int main() {
scanf("%d", &cases);
while( cases-- ) {
scanf("%d %d %d", &n, &K, &MOD);
int i, i1, i2, i3, ... , iK;
for( i = 1; i <= n; i++ ) scanf("%d", &A[i]);
int res = 0;
for( i1 = 1; i1 <= n; i1++ ) {
for( i2 = 1; i2 <= n; i2++ ) {
for( i3 = 1; i3 <= n; i3++ ) {
...
for( iK = 1; iK <= n; iK++ ) {
res = ( res + A[i1] + A[i2] + ... + A[iK] ) % MOD;
}
...
}
}
}
printf("Case %d: %d\n", ++caseno, res);
}
return 0;
}
Actually the code was about: 'You are given three integers and integers: , you have to write nested loops and calculate the summation of all where is the value of any nested loop variable.'
题意
这人写代码写魔怔了,居然做梦都会梦到代码 xO
这次他梦到了一个循环嵌套的屎山代码,给你三个数字 , 和
代表数组 的长度,这意味着你还需要读入他所给的
然后 是嵌套的循环数量, 是你需要用于取模的数(因为答案数值可以非常大)
至于 层循环是什么意思,参考他给出的代码(我修改了下,不过本质不变)
#define foreach(i) for (i = 1; i <= n; i++)
foreach(i1)
foreach(i2)
foreach(i3)
...
foreach(ik)
ans = (ans + a[i1] + a[i2] + a[i3] + ... + a[ik]) % MOD;
输入格式 - Input
Input starts with an integer , denoting the number of test cases.
Each case starts with three integers: . The next line contains non-negative integers denoting . Each of these integers will be fit into a 32 bit signed integer.
第一行为 个整数 ,代表测试样例的数量
每个样例的第一行包含 个整数
第二行包含 个整数
输出格式 - Output
For each case, print the case number and result of the code.
对于每组样例,输出 变量的理论最终值
样例 - Sample
Input | Output |
---|---|
2 3 1 35000 1 2 3 2 3 35000 1 2 |
Case 1: 6 Case 2: 36 |
思路
这题重点在于推导关于 的公式
不妨设 表示 层循环时的答案
则:
数组 的总和
...
使用归纳法可得
因此
计算数组 总和 后,使用快速幂计算 即可
代码
Status | Time | Memory | Length | Lang |
---|---|---|---|---|
Accepted |
12ms | 648kB | 811 | C++ 17 (g++ 7.5.0) |
点击查看代码
#include <iostream>
#include <cstdio>
using namespace std;
typedef long long ll;
ll _, n, k, MOD, sum, ans, a;
ll qpow(ll x, ll power)
{
x %= MOD;
ll res = 1;
for (; power; power >>= 1, (x *= x) %= MOD)
{
if (power & 1)
(res *= x) %= MOD;
}
return res;
}
// i = 1~k, Si = nS(i - 1) + n^(i - 1)S = in^(i - 1)S
// Sk = kn^(k - 1)S
signed main()
{
#ifdef WatPz
string _fn = "Q";
freopen((_fn + ".in").c_str(), "r", stdin);
freopen((_fn + ".out").c_str(), "w", stdout);
#endif
scanf("%lld", &_);
for (ll __ = 1; __ <= _; __++)
{
scanf("%lld%lld%lld", &n, &k, &MOD);
sum = 0;
for (ll i = 1; i <= n; i++)
{
scanf("%lld", &a);
(sum += a) %= MOD;
}
ans = (((k * qpow(n, k - 1)) % MOD) * sum) % MOD;
printf("Case %lld: %lld\n", __, ans);
}
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现