Недавно Филипп вышел на завод с необычным графиком...
創建於:2025年9月11日
創建於:2025年9月11日
Недавно Филипп вышел на завод с необычным графиком работы. Смена Филиппа на заводе будет длиться
n
дней, при этом каждый из дней, у которого ровно
9
делителей, считается выходным. Посчитайте, сколько выходных будет у Филиппа за одну смену на заводе.
Формат входных данных
В первой строке содержится одно целое число
n
(
1
≤
n
≤
4
⋅
10
12
) — продолжительность смены на заводе.
Формат выходных данных
Выведите одно целое число — количество выходных за время одной смены.
Примеры
Входные данные
5
Выходные данные
0
Входные данные
120
Выходные данные
2
Входные данные
365
Выходные данные
5
Примечания
В первом примере Филипп работает без выходных.
Во втором примере выходными считаются дни
36
и
100
.
Хорошо, давайте разберём задачу пошагово.
Пусть число имеет простое разложение:
Число делителей тогда равно:
Нам нужно, чтобы .
Разложение числа 9:
То есть возможны варианты:
.
Тогда , где — простое число.
.
Тогда , где и — разные простые.
Для заданного :
Посчитать количество простых , для которых .
Посчитать количество пар различных простых , для которых
Для :
, нет простых → 0.
, минимальное .
→ Ответ: 0 ✅
Для :
, простых нет.
.
Пары: , .
Другие уже больше.
→ Ответ: 2 ✅
Для :
, значит учитываем . Получаем число .
.
Пары простых :
Алгоритм:
Хотите, я напишу для вас готовый код на Python, который работает даже при ?
давай на c++ но сделать максимально уникальное решение
окей! вот «уникальное» и очень быстрое решение на C++, без плавающих точек, с:
__int128,работает за по времени и по памяти (при это до ~2·10⁶).
cpp#include <bits/stdc++.h> using namespace std; using u64 = unsigned long long; using u128 = __uint128_t; // --------- безопасные целочисленные корни ---------- static inline u64 isqrt_u64(u64 x) { // floor(sqrt(x)) без double u64 lo = 0, hi = (u64)1e10; // т.к. sqrt(4e12) < 2e6 << 1e10; берём большой верхний предел безопасно // но сделаем аккуратнее: верхняя граница не меньше реального корня // можно ослабить: hi = min<u64>(x, (u64)2e9); hi = min<u64>(x, (u64)2000000000ULL); while (lo < hi) { u64 mid = (lo + hi + 1) >> 1; if ((u128)mid * mid <= x) lo = mid; else hi = mid - 1; } return lo; } static inline bool pow_leq(u64 base, int k, u64 lim) { // проверяет base^k <= lim без переполнений u128 acc = 1; for (int i = 0; i < k; ++i) { acc *= base; if (acc > lim) return false; } return true; } static inline u64 iroot_k(u64 n, int k) { // floor(n^(1/k)) бинарным поиском и pow_leq if (k == 1) return n; u64 lo = 0, hi = (k == 2 ? isqrt_u64(n) + 1 : min<u64>(n, (u64)1e6+10)); // небольшой «запас» для hi; для k>=3 корень сильно меньше 1e6 при наших n while (lo < hi) { u64 mid = (lo + hi + 1) >> 1; if (pow_leq(mid, k, n)) lo = mid; else hi = mid - 1; } return lo; } // --------- odd-only битовое sito до MAX ----------- struct OddBitSieve { // храним биты для нечётных: число 2*i+1 соответствует биту i int n; // верхняя граница включительно vector<uint64_t> bits; // 1 = составное, 0 = возможно простое (для нечётных) static inline int idx_of(u64 x) { return int((x - 1) >> 1); } // x нечётное >=1 explicit OddBitSieve(int N): n(N) { int m = (N >= 1) ? (idx_of(N) + 1) : 0; bits.assign((m + 63) >> 6, 0); if (N >= 1) mark(1); // число 1 не простое if (N >= 2) { // классическое просеивание только для нечётных for (u64 p = 3; p * p <= (u64)N; p += 2) { if (!test(p)) { // начинаем с p*p и шагаем по 2p (только нечётные кратные) for (u64 x = p * p; x <= (u64)N; x += (p << 1)) mark((int)x); } } } } inline void mark(int x) { // x нечётное int i = idx_of(x); bits[i >> 6] |= (1ULL << (i & 63)); } inline bool test(int x) const { // true -> составное (для нечётных), false -> «возможно простое» if (x == 2) return false; // 2 отдельный случай if ((x & 1) == 0) return true; // чётные > 2 — составные int i = idx_of(x); return (bits[i >> 6] >> (i & 63)) & 1ULL; } vector<int> primes() const { vector<int> ps; if (n >= 2) ps.push_back(2); for (int x = 3; x <= n; x += 2) if (!test(x)) ps.push_back(x); return ps; } }; int main() { ios::sync_with_stdio(false); cin.tie(nullptr); u64 n; if (!(cin >> n)) return 0; // 1) корни u64 S = isqrt_u64(n); // floor(sqrt(n)) u64 R8 = iroot_k(n, 8); // floor(n^(1/8)) // 2) простые до S OddBitSieve sieve((int)S); vector<int> primes = sieve.primes(); // возрастающий список // 3) количество p^8 <= n <=> p <= R8 u64 cnt_p8 = 0; if (R8 >= 2) { cnt_p8 = upper_bound(primes.begin(), primes.end(), (int)R8) - primes.begin(); } // 4) количество пар различных простых p<q: p*q <= S // двухуказательный приём u64 cnt_pairs = 0; int m = (int)primes.size(); int j = m - 1; for (int i = 0; i < m; ++i) { while (j > i && (u128)primes[i] * (u128)primes[j] > S) --j; if (j <= i) break; cnt_pairs += (u64)(j - i); } cout << (cnt_p8 + cnt_pairs) << '\n'; return 0; }
__int128;сделай решение поменьше и без комментов
cpp#include <bits/stdc++.h> using namespace std; using u64 = unsigned long long; using u128 = __uint128_t; bool pow_leq(u64 a,int k,u64 lim){ u128 x=1; for(int i=0;i<k;i++){ x*=a; if(x>lim) return false; } return true; } u64 iroot(u64 n,int k){ if(k==1) return n; u64 x = (u64)powl((long double)n, 1.0L/k); while(!pow_leq(x,k,n)) --x; while(pow_leq(x+1,k,n)) ++x; return x; } int main(){ ios::sync_with_stdio(false); cin.tie(nullptr); u64 n; if(!(cin>>n)) return 0; u64 S = (u64)sqrtl((long double)n); while((u128)(S+1)*(S+1)<=n) ++S; while((u128)S*S>n) --S; u64 R8 = iroot(n,8); vector<char> is(S+1,true); is[0]=is[1]=false; for(u64 p=2;p*p<=S;++p) if(is[p]) for(u64 x=p*p;x<=S;x+=p) is[x]=false; vector<int> pr; pr.reserve(S/log(max<u64>(2,S))); for(u64 i=2;i<=S;++i) if(is[i]) pr.push_back((int)i); u64 cnt_p8 = upper_bound(pr.begin(), pr.end(), (int)R8) - pr.begin(); u64 ans = cnt_p8, j = pr.size(); for(size_t i=0;i<pr.size();++i){ while(j>i+1 && (u128)pr[i]*pr[j-1]>S) --j; if(j<=i+1) break; ans += (j-1 - (i+1) + 1); } cout<<ans<<"\n"; return 0; }
ладно сделай не уникальным но коротким
cpp#include <bits/stdc++.h> using namespace std; int main() { ios::sync_with_stdio(false); cin.tie(nullptr); unsigned long long n; if (!(cin >> n)) return 0; unsigned long long S = sqrtl((long double)n); while ((S+1)*(S+1) <= n) ++S; while (S*S > n) --S; unsigned long long R8 = powl((long double)n, 1.0L/8); while (powl((long double)R8+1, 8) <= (long double)n) ++R8; while (powl((long double)R8, 8) > (long double)n) --R8; vector<char> is(S+1, true); is[0]=is[1]=false; for (unsigned long long p=2; p*p<=S; ++p) if (is[p]) for (unsigned long long x=p*p; x<=S; x+=p) is[x]=false; vector<int> pr; for (unsigned long long i=2; i<=S; ++i) if (is[i]) pr.push_back((int)i); unsigned long long ans = upper_bound(pr.begin(), pr.end(), (int)R8) - pr.begin(); int m = (int)pr.size(), j = m-1; for (int i=0; i<m; ++i) { while (j>i && (unsigned long long)pr[i]*pr[j] > S) --j; if (j<=i) break; ans += (unsigned long long)(j - i); } cout << ans << '\n'; return 0; }
#include <iostream>
using namespace std;
int main() {
int T;
cin >> T;
while (T--) {
long long a, s;
cin >> a >> s;
long long r = s - 2 * a;
if (r >= 0 && (r & a) == 0) {
cout << "Yes\n";
} else {
cout << "No\n";
}
}
}
повысь уникальность кода
cpp#include <bits/stdc++.h> using namespace std; static inline bool ok(unsigned long long A, unsigned long long S){ if (S < (A<<1)) return false; unsigned long long R = S - (A<<1); return (R & A) == 0; } int main(){ ios::sync_with_stdio(false); cin.tie(nullptr); int t; if(!(cin >> t)) return 0; string out; out.reserve(t*4); for(; t--; ){ unsigned long long a, s; cin >> a >> s; out += ok(a, s) ? "Yes\n" : "No\n"; } cout << out; return 0; }
В одной далекой гильдии алхимиков юный подмастерье по имени Михаил хочет сварить особое зелье мудрости. Для этого ему нужно ровно
s
колб с редким концентратом.
В городе есть
n
лавок, где продаётся этот концентрат. В
i
-й лавке можно купить не более
a
i
колб, и каждая обойдётся Михаилу в
c
i
золотых монет.
Нужно узнать, за какую минимальную сумму золота Михаил сможет купить ровно
s
колб концентрата.
Известно, что в городе всегда можно купить нужное количество колб (т.е. их хватит во всех лавках вместе).
Формат входных данных
Первая строка содержит два целых числа
n
и
s
(
1
≤
n
,
s
≤
100
000
) — количество лавок в городе и желаемое количество колб соответственно.
Следующие
n
строк содержат два целых числа
c
i
и
a
i
(
1
≤
c
i
≤
10
9
,
1
≤
a
i
≤
100
000
), задающих цену и количество колб в
i
-й лавке.
Формат выходных данных
Выведите одно целое число — минимальную сумму золота, за которую можно купить ровно
s
колб концентрата.
Обратите внимание, что ответ может не помещаться в 32-битный тип данных, используйте 64-битные типы (например, long long в C++)
28
золотых монет.
cpp#include <bits/stdc++.h> using namespace std; int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int n; long long s; if (!(cin >> n >> s)) return 0; vector<pair<long long,long long>> v(n); for (auto &p : v) cin >> p.first >> p.second; // (c, a) sort(v.begin(), v.end()); // по цене long long ans = 0; for (auto [c,a] : v) { long long t = min(a, s); ans += t * c; s -= t; if (!s) break; } cout << ans << '\n'; return 0; }