【数学一本通 第一章】SEJ-Strongbox [LUOGU] [POI2011]

密码 [SEJ-Strongbox ]

题目链接:密码 [SEJ-Strongbox ]
(这是一道数论蓝题,想了好长时间啊~~)
【题目大意】
有一个密码箱,0到n-1中的某些整数是它的密码。且满足:如果a和b都是它的密码,那么(a+b)%n也是它的密码(a,b可以相等,%表示整除取余数),某人试了k次密码,前k-1次都失败了,最后一次成功了。
问:该密码箱最多有多少不同的密码。
【样例】

输入:
42 5
28 31 10 38 24
输出:
14

【题解】:

首先从题目中的出的两个结论:
结论一:

如果x为密码,那么 g c d ( x , n ) gcd(x,n) gcdx,n也是密码。

证明:

因为x是密码,由题意得2x%n,3x%n……kx%n都是密码。
由于不定方程 a x + b y = c ax+by=c ax+by=c有整数解的充要条件是 g c d ( a , b ) ∣ c gcd(a,b)|c gcd(a,b)c,所以 x k + n c = g c d ( x , n ) xk+nc=gcd(x,n) xk+nc=gcdx,n一定有整数解,那么 ∃ k ∈ Z ∃k∈Z kZ使 k x ≡ g c d ( x , y ) ( m o d n ) kx ≡ gcd(x,y)(mod n) kxgcdxy(modn),故gcd(x,n)也是密码。

结论二:

如果x,y为密码,那么 g c d ( x , y ) gcd(x,y) gcdx,y也是密码。

证明:

由题意得:以为x,y是密码,显然(px+qy)% n也是密码,因为 x p + y q = g c d ( x , y ) xp+yq=gcd(x,y) xp+yq=gcdxy一定有整数解,那么 ∃ p , q ∈ Z ∃ p,q∈Z p,qZ使得 p x + q y ≡ d ( m o d n ) px+qy≡d(mod n) px+qyd(modn),故 g c d ( x , y ) gcd(x,y) gcdx,y也是密码。

再看看这道题,设 x , y x,y x,y 均为密码且x是所有密码中最小的,若 x ∤ y x∤y xy,则 g c d ( x , y ) &lt; x gcd(x,y)&lt;x gcd(x,y)<x且 gcd(x,y) 是密码(结论二),与假设矛盾,故 x ∣ y x|y xy。因此,这组密码为 x , 2 x , 3 x , ⋯ , k x ( k x &lt; n ) x,2x,3x,⋯,kx (kx&lt;n) x,2x,3x,,kx(kx<n)
d = g c d ( m k , n ) d=gcd(mk,n) d=gcd(mk,n),由于 m k mk mk是密码,根据结论一,d 也是密码,又由①得: x ∣ d x|d xd(仍设x是所有密码中最小的那个)

但是这道题给了一些限制条件:

  1. 要求最多有多少密码,故我们希望x尽量的小,密码数量为n/x
  2. 给出了k−1个不是密码的数字,故 x 不能整除 m1,m2,⋯,mk−1
    综上所述,这道题的实现方法是:在根号的时间里暴力枚举处理出 gcd(mk,n) 的所有因数,去除能整除 m1,m2,⋯,mk−1 中任意一个的数,设剩下的数中最小的为x,则答案就是 n/x
AC代码:
#include<bits/stdc++.h>
#define LL long long
using namespace std;
const int sea=250010;
LL a[sea],q[sea],f[sea],n,k,tot=0,ans;
LL gcd(LL a,LL b){if(a<b) swap(a,b); return b?gcd(b,a%b):a;}
int main()
{
	scanf("%lld%lld",&n,&k);
	for(int i=1;i<=k;i++) scanf("%lld",&a[i]);
	a[k]=gcd(a[k],n);
	for(int i=1;i<k;i++) a[i]=gcd(a[i],a[k]);
	for(LL i=1;i*i<=a[k];i++)
	if(a[k]%i==0) 
	{
		q[++tot]=i;
		if(i!=a[k]/i) q[++tot]=a[k]/i;
	}
	sort(q+1,q+tot+1);
	for(int i=1;i<k;i++)
	f[lower_bound(q+1,q+tot+1,a[i])-q]=1;
	for(int i=1;i<=tot;i++)
	if(f[i])
		for(int j=1;j<i;j++)
		if(q[i]%q[j]==0) f[j]=1;
	ans=1; while(f[ans]) ans++;
	printf("%lld\n",n/q[ans]);
	return 0;
}

continue……

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
1、构建平面函数的MATLAB代码: 假设平面方程为 ax + by + cz + d = 0,其中 a, b, c 是平面法向量的三个分量,d 是平面与原点的距离。输入参数为变换矩阵 T,其中包括平移和旋转操作。 代码如下: ```matlab function [x,y,z] = plane(T,a,b,c,d) % 输入:变换矩阵 T,平面方程系数 a,b,c,d % 输出:平面上的点坐标 x,y,z % 生成平面上的点坐标 [x,y] = meshgrid(-10:0.2:10); z = (-a*x - b*y - d) / c; % 变换平面 pts = [x(:), y(:), z(:)]; pts = pts*T(1:3,1:3)' + T(4,1:3); x = reshape(pts(:,1), size(x)); y = reshape(pts(:,2), size(y)); z = reshape(pts(:,3), size(z)); % 绘制平面 surf(x,y,z); axis equal; end ``` 2、构建求解五棱柱面与平面相交曲线的函数: 假设五棱柱面的底面为正五边形,其顶点为 (0,0,h),其中 h 是五棱柱的高度。平面方程为 ax + by + cz + d = 0,其中 a, b, c 是平面法向量的三个分量,d 是平面与原点的距离。求解过五棱柱面 n 边的平面与平面的交线。 代码如下: ```matlab function [x,y,z] = pentagonal_prism_plane_intersection(a,h,n,T) % 构造底面正五边形 theta = linspace(0,2*pi,6)'; x = a*cos(theta); y = a*sin(theta); z = zeros(size(x)); P = [x(:), y(:), z(:)]; P = P(1:5,:); % 构造顶面正五边形 Q = P + [0, 0, h]; % 构造侧面三角形 I = [1,2,6;2,3,6;3,4,6;4,5,6;5,1,6]; % 将五棱柱移到正确的位置 P = P*T(1:3,1:3)' + T(4,1:3); Q = Q*T(1:3,1:3)' + T(4,1:3); I = I + size(P,1); % 计算平面方程系数 V = Q(1,:) - P(1,:); W = Q(n,:) - P(1,:); N = cross(V,W); N = N / norm(N); a = N(1); b = N(2); c = N(3); d = -dot(N, P(1,:)); % 计算平面与侧面三角形的交点 t = -d / (a*I(:,1) + b*I(:,2) + c*I(:,3)); X = [I(:,1)+t.*(I(:,4)-I(:,1)), I(:,2)+t.*(I(:,5)-I(:,2)), I(:,3)+t.*(I(:,6)-I(:,3))]; % 计算平面与五棱柱底面的交点 t = -d / c; Y = [x(:), y(:), z(:)+t]; % 计算平面与五棱柱顶面的交点 t = -(d + c*h) / c; Z = [x(:), y(:), z(:)+t]; % 绘制交线 x = [X(:,1), Y(:,1), flipud(Z(:,1)), X(1,1)]; y = [X(:,2), Y(:,2), flipud(Z(:,2)), X(1,2)]; z = [X(:,3), Y(:,3), flipud(Z(:,3)), X(1,3)]; plot3(x,y,z,'LineWidth',2); axis equal; end ``` 3、绘制五种平面与五棱柱面相交的曲线: ```matlab % 平面1:水平平面 T1 = eye(4); T1(4,2) = 5; plane(T1,0,0,1,0); pentagonal_prism_plane_intersection(1,4,1,T1); % 平面2:竖直平面 T2 = eye(4); T2(4,1) = 5; plane(T2,1,0,0,0); pentagonal_prism_plane_intersection(1,4,3,T2); % 平面3:斜面 T3 = makehgtform('xrotate',-pi/4,'zrotate',pi/6,'translate',[5,5,0]); plane(T3,1,1,-sqrt(2),0); pentagonal_prism_plane_intersection(1,4,4,T3); % 平面4:过顶点的平面 T4 = makehgtform('yrotate',pi/2,'translate',[-1,-1,4]); plane(T4,0,1,1,0); pentagonal_prism_plane_intersection(1,4,2,T4); % 平面5:过棱边的平面 T5 = makehgtform('yrotate',pi/3,'translate',[-3,3,0]); plane(T5,1,1,1,0); pentagonal_prism_plane_intersection(1,4,3,T5); ``` 结果如下图所示: ![五种平面与五棱柱面相交的曲线](https://i.imgur.com/7iO6sEJ.png)

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值