枚举 坑爹的奥数

/*坑爹的奥数(枚举)
口口口+口口口=口口口
将数字1--9分别填到上面的方框中
每个数字只能使用一次
使得等式成立
EG:
173+286=459
就是一种组合
请问一共有多少组合呢?注:173+286=459  与286+173=459是一种组合!
只需枚举每一位即可 就是酱紫^*^*/
# include <stdio.h>
int main(){
	int A,B,C,D,E,F,G,H,I,SUM=0;
	int X,Y,Z;
	for(A=1;A<=9;A++)
		for(B=1;B<=9;B++)
			for(C=1;C<=9;C++)
				for(D=1;D<=9;D++)
					for(E=1;E<=9;E++)
						for(F=1;F<=9;F++)
							for(G=1;G<=9;G++)
								for(H=1;H<=9;H++)
									for(I=1;I<=9;I++)
										if(A!=B&&A!=C&&A!=D&&A!=E&&A!=F&&A!=G&&A!=H&&A!=I
											&&B!=C&&B!=D&&B!=E&&B!=F&&B!=G&&B!=H&&B!=I
											&&C!=D&&C!=E&&C!=F&&C!=G&&C!=H&&C!=I
											&&D!=E&&D!=F&&D!=G&&D!=H&&D!=I
											&&E!=F&&E!=G&&E!=H&&E!=I
											&&F!=G&&F!=H&&F!=I
											&&G!=H&&G!=I
											&&H!=I)
										{
											X=A*100+B*10+C;
											Y=D*100+E*10+F;
											Z=G*100+H*10+I;
											if(X+Y==Z&&X<Y)
											{
													SUM++;
													printf("%d+%d=%d\n",X,Y,Z);
												if(X==386)//此处是为了快速跳出循环 得到正确的结果后又加上的
													goto AAA;//没有它 时间会>2S
											}
										}
AAA:printf("SUM=%d",SUM);
	return 0;
}

以上是朴素的解法 下面是遍历:

/*用全排列也可以*/
# include <stdio.h>
# define N 11   //几位数 
int X,Y,Z,SUM=0;
void DFS(int A[2][N],int step);//A为二维数组 初始化为0 M为A种用的数组长度 step用于递归
int main(){
	int A[2][N]={0};//A[0]存放数字 A[1]存放标志
	DFS(A,1);
	printf("SUM=%d",SUM);
	return 0;
}
void DFS(int A[2][N],int step)//递归
{
	int i;
    if(step==10)    //如果前M个已经排好 此时赢直接输出 并停止递归
	{
	    X=A[0][1]*100+A[0][2]*10+A[0][3];
		Y=A[0][4]*100+A[0][5]*10+A[0][6];
		Z=A[0][7]*100+A[0][8]*10+A[0][9];
		if(Z==X+Y&&X<Y)
		{
		   SUM++;
		   printf("%d+%d=%d\n",X,Y,Z);
		}
		return;    //如果没有return  程序会无休止的循环下去
	}
	for(i=1;i<10;i++)
	{
	    if(!A[1][i])   //当此前的数字没有在函数中使用
		{
		   A[0][step]=i;
		   A[1][i]=1;
		   DFS(A,step+1);
		   A[1][i]=0;//使用过后记为0
		}	
	}
	return;
}

附加小程序:

/*
快速幂运算
模运算:计算除以M的余数 即对M取模
我们将A B除以M后所得的余数相等的情况下 记作A==B(mod M) 规定A(mod M)∈[0,M-1]
基本运算:
假设:A==C(mod M)  B==D(mod M)
则:
A+B==C+D (mod M)
A-B==C-D (mod M)
A*B==C*D (mod M)
对于除法:不是所有的除法都成立
当A*C==B*C(mod M)时 (A-B)*C就可以被M整除
当满足 C与M的最大公因数为D时 即D=GYS(C,M)时 
(A-B)*(C/D)就可以被M/D整除  又C/D 与M/D的最大公因数为1
所以 A-B可以被M/D整除即  A==B(mod M/GYS(M,C))

  
	快速幂运算
	题目:我们把任意的X∈(1,N)都有X^N=X(modN)成立的合数N 叫做Carmichael Number
	对于给定的整数N 请判断它是不是Carmichael Number
	limit N∈[2,65000]
	time<=1S
	EG:
	输入N= 17  输出 NO 
	输入N=561  输出 YES
	
	  此题目可以用O(sqrt(N))判断是不是质数
	  有N个待检查数,如果每个数都按照定义O(N)来计算幂 总的时间复杂度为0(N^2) 不能满足时间上的要求
	  
		如果 N=2^k
		则可以将其表示为 X^N=(((X^2)^2))……
		即:N=2^K1 +2^K2 +2^K3+……
		就有:
		X^N=X^(2^K1) +X^(2^K2) +X^(2^K3)+……
		
		  依次求X^(2^i)即可 复杂度O(logN)
		  根据二进制
		  EG :22(10)=10110(2)
		  所以 22=16+4+2 二进制可以快速的求结果
		  代码:
*/
# include <stdio.h>
typedef __int64 INT;
# define M 10000000
# define MAX 65000
char ZU[MAX+2]={"\0"};//全部初始化为0
INT MI(INT X,INT N,INT mod);//非递归
//INT MID(INT X,INT N,INT mod);//递归与MI功能相同 可以替换上面的MI函数
void AZS(INT N);//埃氏筛法 求出N以内的所有素数 若i是素数则ZU[i]=0
int main(){
    INT N,I;
	scanf("%I64d",&N);
	AZS(MAX);//求出MAX内的所有质数
	if(!ZU[N])//如果是质数显然为NO 因为N必须为合数
	{
		printf("NO\n");
		return printf("NO\n");
	}
	else for(I=2;I<N;I++)//如果N为合数
		if(I!=MI(I,N,N))//if(I!=MID(I,N,N))
		{
			printf("NO");
			return 0;
		}
		printf("YES\n");
		return 0;
}
void AZS(INT N)//求出N以内的所有素数
{
    int i,j;
	for(i=2;i<=N;i++)
		if(!ZU[i])
			for(j=2*i;j<=N;j+=i)
				ZU[j]=1;
}
INT MI(INT X,INT N,INT mod)//非递归
{
	INT sum=1;
	while(N>0)
	{
		if(N&1) sum=sum*X%mod;  //N&1 即取N的末位
		X=X*X%mod;
		N>>=1;               //N>>=1 即去掉N的二进制末位 也就是 N/=2;
	}
	return sum;
}
/*INT MID(INT X,INT N,INT mod)//递归
{
INT sum;
if(!N) return 1;  //当N位数全部用完 返回1
sum=MID(X*X%mod,N/2,mod);
if(N&1) sum=sum*X%mod;
return sum;
}*/


  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值