素数,指的是除 1 和它本身之外没有其他约数的数。
基本知识->判断素数的常用方法<-
[NOIP2012 普及组] 质因数分解
题目描述
已知正整数 n n n 是两个不同的质数的乘积,试求出两者中较大的那个质数。
输入格式
输入一个正整数 n n n。
输出格式
输出一个正整数 p p p,即较大的那个质数。
样例 #1
样例输入 #1
21
样例输出 #1
7
提示
1 ≤ n ≤ 2 × 1 0 9 1 \le n\le 2\times 10^9 1≤n≤2×109
NOIP 2012 普及组 第一题
代码实现
#include<iostream>
using namespace std;
int main()
{
int n;
cin>>n;
for(int i=2;i<=n;i++)
{
if(n%i==0)
{
cout<<n/i;
return 0;
}
}
return 0;
}
角色属性树
题目描述
绪萌同人社是一个有趣的组织,该组织结构是一个树形结构。有一个社长,直接下属一些副社长。每个副社长又直接下属一些部长……。
每个成员都有一个萌点的属性,萌点属性是由一些质数的萌元素乘积构成(例如,猫耳的值是 2 2 2,弱气的值是 3 3 3,黄毛的值是 5 5 5,病娇的值是 7 7 7,双马尾的值是 11 11 11 等等)
举个例子,正妹是双份的猫耳,而且有一份弱气,她的属性值为 2 × 2 × 3 = 12 2\times 2\times 3=12 2×2×3=12。
现在组员关心一个问题,希望知道离自己最近且有相同萌元素上司是谁,例如,属性值为 2 、 4 、 6 、 45 2、4、6、45 2、4、6、45 这样的属性值都算是和正妹有相同的属性。
然而,组员可能会随时变化自己的属性。啊。。感觉好麻烦啊。。
输入格式
第一行, n , k n,k n,k 表示成员数与询问的次数
第二行, n n n 个数,分别是 1 1 1 到 n n n 号成员的属性值
接下来 n − 1 n-1 n−1 行, x i , y i x_i,y_i xi,yi 表示 x i x_i xi 是 y i y_i yi 的上司。
接下来来 k k k 行,有两种情况
1 u i 1\ u_i 1 ui:询问离 u i u_i ui 成员最近且有相同萌元素上司。
2 u i 2\ u_i 2 ui: a a a 更改 u i u_i ui 的属性值为 a a a。
输出格式
对于每个 1 1 1 类型的询问,输出符合要求的编号。如果没有符合要求的编号,输出 − 1 -1 −1。
样例 #1
样例输入 #1
4 6
10 8 4 3
1 2
2 3
3 4
1 1
1 2
1 3
1 4
2 1 9
1 4
样例输出 #1
-1
1
2
-1
1
提示
对于 20 % 20\% 20% 的数据,没有修改的操作。
对于 50 % 50\% 50% 的数据, n ≤ 100 n\le 100 n≤100,修改次数 < 10 <10 <10。
对于 100 % 100\% 100% 的数据, n ≤ 200000 n\le 200000 n≤200000, k < 100000 k<100000 k<100000,修改次数 ≤ 50 , a _ i ≤ 2 31 − 1 \le 50,a\_i\le 2^{31}-1 ≤50,a_i≤231−1
UPD:本题测试数据随机,可能是假题。
解题思路
记录每个节点的父节点,查询时一路向上寻找并计算gcd(最大公约数)就好,gcd>1说明二者包含相同的质数。
代码实现
#include<iostream>
#include<vector>
using namespace std;
#define MAX_N 200000
#define MAX_K 100000
int val[MAX_N+5];
int fa[MAX_N+5];
int n,k;
int gcd(int a,int b)
{
return b==0?a:gcd(b,a%b);
}
void dfs(int now,int father)
{
if(father==0)
{
cout<<-1<<endl;
return ;
}
if(gcd(val[now],val[father])>1)
{
cout<<father<<endl;
return ;
}
dfs(now,fa[father]);
return ;
}
int main()
{
cin>>n>>k;
for(int i=1;i<=n;i++)cin>>val[i];
for(int i=1,a,b;i<=n-1;i++)
{
cin>>a>>b;
fa[b]=a;
}
for(int i=1,a,b,c;i<=k;i++)
{
cin>>a;
if(a==1)
{
cin>>b;
dfs(b,fa[b]);
}
else if(a==2)
{
cin>>b>>c;
val[b]=c;
}
}
return 0;
}
【XR-3】小道消息
题目描述
小 X 想探究小道消息传播的速度有多快,于是他做了一个社会实验。
有 n n n 个人,其中第 i i i 个人的衣服上有一个数 i + 1 i+1 i+1。小 X 发现了一个规律:当一个衣服上的数为 i i i 的人在某一天知道了一条信息,他会在第二天把这条信息告诉衣服上的数为 j j j 的人,其中 gcd ( i , j ) = 1 \gcd(i,j)=1 gcd(i,j)=1(即 i , j i,j i,j 的最大公约数为 1 1 1)。在第 0 0 0 天,小 X 把一条小道消息告诉了第 k k k 个人,小 X 想知道第几天时所有人都会知道这条小道消息。
可以证明,一定存在所有人都知道了这条小道消息的那一天。
提示:你可能需要用到的定理——伯特兰-切比雪夫定理。
输入格式
一行 2 2 2 个正整数 n , k n,k n,k。
数据范围:
- 2 ≤ n ≤ 1 0 14 2 \le n \le 10^{14} 2≤n≤1014。
- 1 ≤ k ≤ n 1 \le k \le n 1≤k≤n。
输出格式
一行一个正整数,表示答案。
样例 #1
样例输入 #1
3 1
样例输出 #1
2
样例 #2
样例输入 #2
6 4
样例输出 #2
1
提示
【样例 1 1 1 说明】
3
3
3 个人的衣服上的数分别为 2 3 4
。
在第 0 0 0 天,小 X 把一条小道消息告诉了第 1 1 1 个人,他的衣服上的数为2。
在第 1 1 1 天,第 1 1 1 个人会告诉第 2 2 2 个人,因为 gcd ( 2 , 3 ) = 1 \gcd(2,3) = 1 gcd(2,3)=1,但他不会告诉第 3 3 3 个人,因为 gcd ( 2 , 4 ) = 2 ≠ 1 \gcd(2,4) = 2 \ne 1 gcd(2,4)=2=1。
在第 2 2 2 天,第 2 2 2 个人会告诉第 3 3 3 个人,因为 gcd ( 3 , 4 ) = 1 \gcd(3,4) = 1 gcd(3,4)=1,这时所有人都知道了这条小道消息,因此答案为 2 2 2。
解题思路
伯特兰—切比雪夫定理说明:若整数n>3,则至少存在一个质数p,符合n<p<2n − 2。另一个稍弱说法是:对于所有大于1的整数n,至少存在一个质数p,符合n<p<2n。
容易证明,只要我们找到大于(n+1)/2的素数,我们下一天可以直接完成消息传播。切比雪夫定理为我们判断能否找到>(n+1)/2的素数提供了理论基础,也就是说,只要我们一开始拥有一个数,第一天我们就能解锁这个大于(n+1)/2的素数,因此至少第二天就能完成消息传播。
1.如果第0天得到的是一个小于(n+1)/2的素数,需要两天完成消息传递;2.如果第0天得到的是一个大于(n+1)/2的素数,一天就可以完成消息传递;3.如果第0天得到的是一个合数,需要两天完成消息传递。
代码实现
#include<iostream>
#include<cmath>
using namespace std;
bool is_prim(long long x)
{
for(long long i=2;i<=sqrt(x);i++)
{
if(x%i==0)
return 0;
}
return 1;
}
int main()
{
long long n,k;
cin>>n>>k;
int flag=is_prim(k+1);
if(!flag)cout<<2;
else if(flag)
{
if(k+1>(n+1)/2)cout<<1;
else cout<<2;
}
return 0;
}