[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" ...
随机推荐
- 14: curl#6 - "Could not resolve host: mirrorlist.centos.org; 未知的错误"
14: curl#6 - "Could not resolve host: mirrorlist.centos.org; 未知的错误" One of the configured ...
- Invalid ON UPDATE clause for 'create_date' column
高版本的mysql导数据到低版本出现的问题 日期类型报错 解决方式:将datetime DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP COMMENT 中的 ON ...
- 使用Java中Calendar类测试当前年月日
import java.util.Calendar; public class time { public static void main(String[] args) { Calendar cal ...
- 洛谷——P2171 Hz吐泡泡
P2171 Hz吐泡泡 题目描述 这天,Hz大大心血来潮,吐了n个不同的泡泡玩(保证没有重复的泡泡).因为他还要写作业,所以他请你帮他把这些泡泡排序成树(左子树<=根<右子树).输出它的后 ...
- manacher(马拉车)算法
断断续续地看了两天的马拉车算法,可算是给搞明白了(贼开心),这算是自己搞懂的第一个算法了(23333333333333)这个算法照目前自己的理解来看,貌似就只能求个字符串中的回文串(接触这个算法是要求 ...
- 爬虫之pyquery库
官方文档:https://pyquery.readthedocs.io/en/latest/ PyQuery是一个强大又灵活的网页解析库.如果你觉得正则写起来太麻烦.BeautifulSoup语法太难 ...
- C语言中指针的加减运算
参考文章,值得一看 char arr[3]; printf("arr:\n%d\n%d\n%d\n", arr, arr + 1, arr + 2); char *parr[3]; ...
- 关于图片预览使用base64在chrome上的性能问题解决方法
在开发后台上传图片的功能时候使用base64预览图片,结果在传入大量图片后导致chrome崩溃,代码如下 var img = new Image(); var render = new FileRea ...
- 1031. Hello World for U
Given any string of N (>=5) characters, you are asked to form the characters into the shape of U. ...
- Java面试题大全(javaSe,HTML,CSS,js,Spring框架等)
目录 1. Java基础部分 7 1.一个".java"源文件中是否可以包括多个类(不是内部类)?有什么限制? 7 2.Java有没有goto? 7 3.说说&和& ...