[Codeforces 485F] Oppa Funcan Style Remastered
[题目链接]
https://codeforces.com/contest/986/problem/F
[算法]
不难发现 , 每个人都在且仅在一个简单环中 , 设这些环长的长度分别为
A1, A2 , A3 ... Alen, 那么有 :
1. A1 + A2 + A3 + .. + Alen = n
2. A1 , A2 , .. Alen为k的因子且大于或等于2
显然 , 每一个k的因数都可以分成若干个k的质因子之和 , 因此我们可以将问题转化为求是否存在 :
B1P1 + B2P2 + ... BmPm = n (其中,m为质因子的个数)
当m = 0时, 显然无解
当m = 1时 ,若n为P1的倍数 , 则有解 , 否则无解
当m = 2时 , 问题就转化为判断一个形如 :Ax + By = C , GCD(A,B) = 1的不定方程是否有非负整数解 , 我们可以用拓展欧几里得或其他算法解决 , 不再赘述
当m >= 3时 , 显然 , 最小的质因子一定小于等于k ^ (1 / 3), k最大时达到10 ^ 15 , 因此 , k ^ (1 / 3)不会超过10 ^ 5 , 我们不妨建10^5个点 ,
若(i + Pi) mod P1 = j mod P1 , 则从i向j连一条权值为Pi的边。
然后我们从0号点开始单源最短路 , 求得的最短路Dist[i]表示通过k的质因子组合出的,模P1余i的数中最小的 , 显然 , 若n >= Dist[n mod P1] , 问题有解 , 否则无解。
下面我们分析整个算法的时间复杂度 :
令Q = 50( 不同的k的个数 )
首先 , 为了减少在分解质因数上花费的时间 , 我们需要预处理质数 , 这将花费我们O( sqrt(K) ) )的时间 , 其中sqrt表示开根号
对于每个询问 , 我们需要将k分解质因数 , 我们需要花费O(Q * sqrt(K) / log(K))的时间 , 其中sqrt表示开根号
当m <= 2时我们需花费O(1) - O(logN)的时间 , 共需O(TlogN)的时间
当m >= 3时我们需要花费O(Q * k ^( 1 / 3) * logk)计算单源最短路( 需使用高效的Dijkstra + 堆算法 )
综上 , 总时间复杂度为 : O( sqrt(k) + Q * ( sqrt(k) / log(k) + k ^ (1 / 3)logk ) + TlogN) , 可以通过此题
[代码]
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll MAXN = 1e18;
const ll MAXK = 1e15;
const ll INF = 4e18;
const int MAXV = 3.2e7 + ;
const int MAXP = 2e6 + ;
const int MAXF = 1e5 + ;
const int MAXQ = ;
const int MAXLOG = ; ll n,k,tot,q;
int f[MAXV],prime[MAXP],cnt[MAXQ + ];
ll p[MAXQ + ][MAXLOG],dist[MAXQ + ][MAXF];
ll mem[MAXQ];
bool visited[MAXP]; template <typename T> inline void read(T &x)
{
ll f = ; x = ;
char c = getchar();
for (; !isdigit(c); c = getchar()) if (c == '-') f = -f;
for (; isdigit(c); c = getchar()) x = (x << ) + (x << ) + c - '';
x *= f;
}
inline ll exp_mod(ll a,ll n,ll p)
{
ll res = , b = a;
while (n > )
{
if (n & ) res = res * b % p;
b = b * b % p;
n >>= ;
}
return res;
} int main()
{ int T;
read(T);
for (int i = ; i < MAXV; i++)
{
if (!f[i]) prime[++tot] = f[i] = i;
for (int j = ; j <= tot; j++)
{
int tmp = i * prime[j];
if (tmp >= MAXV) break;
f[tmp] = prime[j];
if (f[i] == prime[j]) break;
}
}
while (T--)
{
read(n); read(k);
if (k == )
{
printf("NO\n");
continue;
}
int pos = ;
for (int i = ; i <= q; i++)
if (mem[i] == k) pos = i;
if (!pos)
{
pos = ++q;
mem[pos] = k;
cnt[pos] = ;
for (int i = ; 1ll * prime[i] * prime[i] <= k; i++)
{
if (k % prime[i] == )
{
p[pos][++cnt[pos]] = prime[i];
while (k % prime[i] == ) k /= prime[i];
}
}
if (k != ) p[pos][++cnt[pos]] = k;
if (cnt[pos] >= )
{
for (int i = ; i < p[pos][]; i++)
{
dist[pos][i] = INF;
visited[i] = false;
}
dist[pos][] = ;
static priority_queue< pair<ll,int> > q;
q.push(make_pair(,));
while (!q.empty())
{
int u = q.top().second;
q.pop();
if (visited[u]) continue;
visited[u] = true;
for (int i = ; i <= cnt[pos]; i++)
{
int to = (u + p[pos][i]) % p[pos][];
int w = p[pos][i];
if (dist[pos][u] + w < dist[pos][to])
{
dist[pos][to] = dist[pos][u] + w;
q.push(make_pair(-dist[pos][to],to));
}
}
}
}
}
if (cnt[pos] == )
{
if (n % p[pos][] == )
{
printf("YES\n");
continue;
} else
{
printf("NO\n");
continue;
}
}
if (cnt[pos] == )
{
ll b = n % p[pos][] * exp_mod(p[pos][] , p[pos][] - ,p[pos][]) % p[pos][];
if (b * p[pos][] <= n) printf("YES\n");
else printf("NO\n");
continue;
}
int val = n % p[pos][];
if (n >= dist[pos][val]) printf("YES\n");
else printf("NO\n");
} return ; }
[Codeforces 485F] Oppa Funcan Style Remastered的更多相关文章
- Codeforces 986F - Oppa Funcan Style Remastered(同余最短路)
Codeforces 题面传送门 & 洛谷题面传送门 感谢此题教会我一个东西叫做同余最短路(大雾 首先这个不同 \(k\) 的个数 \(\le 50\) 这个条件显然是让我们对每个 \(k\) ...
- CF986F Oppa Funcan Style Remastered
CF986F Oppa Funcan Style Remastered 不错的图论转化题! 题目首先转化成:能否用若干个k的非1因数的和=n 其次,因数太多,由于只是可行性,不妨直接都用质因子来填充! ...
- 「CF986F」 Oppa Funcan Style Remastered
「CF986F」 Oppa Funcan Style Remastered Link 首先发现分解成若干个 \(k\) 的因数很蠢,事实上每个因数都是由某个质因子的若干倍组成的,所以可以将问题转换为分 ...
- [CF986F]Oppa Funcan Style Remastered[exgcd+同余最短路]
题意 给你 \(n\) 和 \(k\) ,问能否用 \(k\) 的所有 \(>1\) 的因子凑出 \(n\) .多组数据,但保证不同的 \(k\) 不超过 50 个. \(n\leq 10^{1 ...
- codeforces986F Oppa Funcan Style Remastered【线性筛+最短路】
容易看出是用质因数凑n 首先01个因数的情况可以特判,2个的情况就是ap1+bp2=n,b=n/p2(mod p1),这里的b是最小的特解,求出来看bp2<=n则有解,否则无解 然后剩下的情况最 ...
- CodeForces 150E: Freezing with Style
题目传送门:CF150E. 据说这个傻逼题还有一个 \(\log\) 的做法,但是我还不会. 题意简述: 给定一棵 \(n\)(\(2\le n\le 10^5\))个点的树,边有边权. 定义一条路径 ...
- 一句话题解&&总结
CF79D Password: 差分.两点取反,本质是匹配!最短路+状压DP 取反是套路,匹配是发现可以把操作进行目的化和阶段化,从而第二次转化问题. 且匹配不会影响别的位置答案 sequence 计 ...
- CodeForces - 344B Simple Molecules (模拟题)
CodeForces - 344B id=46665" style="color:blue; text-decoration:none">Simple Molecu ...
- CodeForces - 344D Alternating Current (模拟题)
id=46667" style="color:blue; text-decoration:none">CodeForces - 344D id=46667" ...
随机推荐
- CAD利用Select2得到所有实体(网页版)
主要用到函数说明: IMxDrawSelectionSet::Select2 构造选择集.详细说明如下: 参数 说明 [in] MCAD_McSelect Mode 构造选择集方式 [in] VARI ...
- 如何在网页中浏览和编辑DWG文件 梦想CAD控件
如何在网页中浏览和编辑DWG文件 梦想CAD控件 www.mxdraw.com 梦想绘图控件5.2 是国内最强,最专业的CAD开发组件(控件),不需要AutoCAD就能独立运行.控件使用VC 201 ...
- css--小白入门篇1
一.引入 css用来描述html,学习css前我们先来学习html的基础标签的用法,再进入css的学习. 本教程面向小白对象,不会讲细枝末节深入的东西. 二.列表 列表有3种 2.1 无序列表 无序列 ...
- [Luogu] P4626 一道水题 II
---恢复内容开始--- 题目描述 一天,szb 在上学的路上遇到了灰太狼. 灰太狼:帮我们做出这道题就放了你. szb:什么题? 灰太狼:求一个能被 [1,n] 内所有数整除的最小数字,并对 100 ...
- vuex----mutation和action的基本使用
我们要实现的很简单,就是点击+1的count加一,点击-1的时候count-1 一.mutation 在vue 中,只有mutation 才能改变state. mutation 类似事件,每一个mu ...
- 洛谷 2484 [SDOI2011]打地鼠
[题解] n^6的做法很好想,然而这样复杂度不对.. 然后我们可以发现R和C可以分开求,这样复杂度降到了n^4. 使用树状数组可以把复杂度降到n^3logn,可以顺利通过. #include<c ...
- BZOJ 4385 洛谷3594 POI2015 WIL-Wilcze doły
[题解] 手残写错调了好久QAQ...... 洛谷的数据似乎比较水.. n个正整数!!这很重要 这道题是个类似two pointer的思想,外加一个单调队列维护当前区间内长度为d的子序列中元素之和的最 ...
- 【Codeforces 582A】GCD Table
[链接] 我是链接,点我呀:) [题意] 给你一个数组A[]经过a[i][j] = gcd(A[i],A[j])的规则生成的二维数组 让你求出原数组A [题解] 我们假设原数组是A 然后让A数组满足A ...
- Non-inclusive cache method using pipelined snoop bus
A non-inclusive cache system includes an external cache and a plurality of on-chip caches each havin ...
- 最小生成树 B - Networking
You are assigned to design network connections between certain points in a wide area. You are given ...