BZOJ 2277 Poi2011 Strongbox 数论

题目大意:给定n和k个整数,求mod n加法下的群G的一个子群G‘,满足a[1]~a[k-1]都不在群中而a[k]在群中

首先易证G‘一定是一个循环群

证明:显然若a在群中则a的逆元在群中

那么我们就有了减法运算

由群的封闭性可得若a和b都在群中则gcd(a,b)一定在群中

不妨设g为G‘中所有元素的gcd 那么群G‘‘={0,g,2g,...}一定是G‘的一个子群

由于G‘-G‘‘中的所有元素均不是g的倍数,故G‘∩(G‘-G‘‘)为空 G‘=G‘‘

由此可得G‘是以g为最小生成元的一个循环子群 大小为n/g

上面都是废话

总之我们现在就要找到一个数g,使得g|n且g|a[k],且对于任意1<=i<=k-1,g不是a[i]的约数

这个MS没有什么办法直接做

我们发现10^14以内的数约数个数最多只有17280个

因此我们将a[1]~a[k-1]中所有的数对n取gcd,排序去重,这样k的规模就减小到了17280

然后枚举gcd(n,a[k])的所有约数,暴力验证,取最小的g就是结果

时间复杂度O(√n+klogn+17280^2)

卡爆了

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define M 250250
using namespace std;
int k,tot;
long long n,ans,a[M];
void Check(long long x)
{
	int i;
	for(i=1;i<=tot;i++)
		if(a[i]%x==0)
			return ;
	ans=min(ans,x);
}
int main()
{
	int i;
	cin>>n>>k;ans=n;
	for(i=1;i<=k;i++)
	{
		#ifdef ONLINE_JUDGE
			scanf("%lld",&a[i]);
		#else
			scanf("%I64d",&a[i]);
		#endif
		a[i]=__gcd(n,a[i]);
	}
	sort(a+1,a+k);
	for(i=1;i<k;i++)
		if(i==k+1||a[i]!=a[i+1])
			a[++tot]=a[i];
	for(i=1;(long long)i*i<=a[k];i++)
		if(a[k]%i==0)
		{
			Check(i);
			Check(a[k]/i);
		}
	cout<<n/ans<<endl;
	return 0;
}
时间: 2024-08-05 02:30:54

BZOJ 2277 Poi2011 Strongbox 数论的相关文章

bzoj 4176 Lucas的数论

bzoj 4176 Lucas的数论 和约数个数和那题差不多.只不过那个题是多组询问,这题只询问一次,并且 \(n\) 开到了 \(10^9\). \[ \begin{align*} \sum_{i=1}^N \sum_{j=1}^N f(ij)&= \sum_{i=1}^N \sum_{j=1}^N \sum_{x|i} \sum_{y|j}[gcd(x,y)=1]\\&= \sum_{i=1}^N \sum_{j=1}^N \sum_{x|i} \sum_{y|j} \sum_{d|g

[poi2011]bzoj 2277 —— strongbox&#183;[洛谷3518]

·问题描述· 有一个密码箱,0到n-1中的某些数是它的密码.且满足:如果a和b都是它的密码,那么(a+b)%n也是它的密码.某人试了k次密码,前k-1次都失败了,最后一次成功. 问:该密码箱最多有多少个密码? ·输入格式· 输入第一行两个整数分别表示n,k. 第二行为k个用空格隔开的非负整数,表示每次试的密码.(数据保证存在合法解) ·输出格式· 输出一行一个数,表示结果. ·输入样例· 42 5 28 31 10 38 24 ·输出样例· 14 ·数据范围· 对于100%的数据:1<=k<=

BZOJ 1406 [AHOI2007]密码箱 数论

题意:链接 方法:数论 解析: 对于这道题,假设n=a*b;然后b是较大的因子 之后怎么来想呢? 之后就是根号找因子,找到每个a,b,之后从0~n枚举b的倍数. 因为x2?1=0(mod n) 所以(x?1)?(x+1)=0(mod n) 因为我们枚举的数就是k1*b,所以我们只要讨论一下,k1*b是等于x-1还是x+1就好了,之后就是判断下边界什么的就把所有的可能值加到一个set里!千万不要犯傻加到map里!!千万不要!!不要认为map啥都能干!! 之后因为set内元素的唯一性.直接输出内部所

[BZOJ 2350] [Poi2011] Party 【Special】

题目链接: BZOJ - 2350 题目分析 因为存在一个 2/3 n 大小的团,所以不在这个团中的点最多 1/3 n 个. 牺牲一些团内的点,每次让一个团内的点与一个不在团内的点抵消删除,最多牺牲 1/3 n 个团内的点,至少剩余一个 1/3 n 的团. 如果两个点之间没有边,那么至少有一个点在团外,删掉这两个点! 代码 #include <iostream> #include <cstdlib> #include <cstring> #include <cst

[BZOJ 2212] [Poi2011] Tree Rotations 【线段树合并】

题目链接:BZOJ - 2212 题目分析 子树 x 内的逆序对个数为 :x 左子树内的逆序对个数 + x 右子树内的逆序对个数 + 跨越 x 左子树与右子树的逆序对. 左右子树内部的逆序对与是否交换左右子树无关,是否交换左右子树取决于交换后 “跨越 x 左子树与右子树的逆序对” 是否会减小. 因此我们要求出两种情况下的逆序对数,使用线段树合并,对每个节点建一棵线段树,然后合并的同时就求出两种情况下的逆序对. 代码 #include <iostream> #include <cstdli

[BZOJ] 2276: [Poi2011]Temperature

2276: [Poi2011]Temperature Time Limit: 20 Sec  Memory Limit: 32 MBSubmit: 731  Solved: 334[Submit][Status][Discuss] Description The Byteotian Institute of Meteorology (BIM) measures the air temperature daily. The measurement is done automatically, an

●BZOJ 4176 Lucas的数论

题链: http://www.lydsy.com/JudgeOnline/problem.php?id=4176 题解: 莫比乌斯反演,杜教筛 首先有这么一个结论: 令d(n)表示n的约数的个数(就是题目中的f(n)),则有 $$d(nm)=\sum_{i|n}\sum_{j|m}[gcd(i,j)==1]$$ ●BZOJ 3994 [SDOI2015]约数个数和也用到了这个东西. 那么就下来接直接进行求ANS的式子的推导: $$\begin{aligned}ANS&=\sum_{n=1}^{N

BZOJ 2525 [Poi2011]Dynamite 二分+树形贪心

题意: n个点,一棵树,有些点是关键点,可以将m个点染色. 求所有关键点到最近的被染色点的距离的最大值最小. 解析: 反正从这道题我是学了一种做题思路? 大爷讲课的时候说的:一般选择某些点的代价相同的话都是贪心,代价不同的话一般都是DP. 想想也挺对的,不过就是没有感悟到过? 反正这题考试的时候我是直接D了贪心的- -! 忘了为啥D了. 显然最大值最小我们需要二分一下这个值. 然后接下来我们从下往上扫整棵树. 节点的状态有几个? 第一种是 子树内没有不被覆盖的关键点,并且子树中有一个节点的贡献可

BZOJ 4176 Lucas的数论 莫比乌斯反演

题目大意:给定n(n≤109),求∑ni=1∑nj=1d(ij) 推错式子害死人... 由d|ij等价于dgcd(i,d)|j可得 ∑ni=1∑nj=1d(ij) =∑ni=1∑n2d=1?n?gcd(i,d)d? =∑nd=1∑?nd?i=1∑?n2d?j=1?nj?[gcd(i,j)=1] =∑nd=1∑?nd?i=1∑nj=1?nj?[gcd(i,j)=1] =∑nd=1∑?nd?i=1∑nj=1?nj?∑k|i,k|jμ(k) =∑nk=1μ(k)(∑?nk?d=1?nkd?)2 O(n