codeforces 376C Divisible by Seven(能被7整除的数)

题目链接:

http://codeforces.com/problemset/problem/376/C

题目大意:

给一个很大的数,这个数一定包含1,6,8,9这4个数字,当然可能还有其他数字。现在要重新排列这些数字获得一个新的数字,要求不出现前导零并且被7整除。

思路:

能被7整除的数,一定是有规律可循的。

先明确:10的零次幂除以7余1;
          10的一次幂除以7余3;
          10的二次幂除以7余2;
          10的三次幂除以7余6;
          10的四次幂除以7余4;
          10的五次幂除以7余5;
          10的六次幂除以7余1(循环了)、、、
对于任意一个数,用其相应位数乘以位数幂的余数,这几个数相加以后,看和能不能被7整除,如果能被整除那么这个数也一定能被整除。

比如343=3*2+4*3+3*1->21能被7整除。

那么再看这道题,因为一定有1,6,8,9这4个数字,而这4个数字的组合方式有24种。不同的组合我们可以发现他们除以7取余数的范围是0-6,也就是说,我们可以通过构造一个新的能被7整除的数来解决这个问题。

所以对于一个大数,我们可以先除去0,然后选出1,6,8,9这4种数字(每种只选一个),剩下的那些数字我们可以相加取模,那么就可以得到除以7以后的余数x。然后我们再把含有1,6,8,9的四位数放到后面,就是形成了[num][1689]的形式。那么num所处的位置是10的四次幂,所以我们可以计算出4*x,只要取[1689]中的某一个组合获得余数y,使得4*x+y能被7整除即可。


代码:

#include<stdio.h>
#include<string.h>
 char s[1000005],ans[1000005];
 char ap[10][5]={"1869","1968","1689","6198","1698","1986","1896"};  //分别代表余数从0-6的组合
int main()
{
  int i,j,k,l,num,f1,f2,f3,f4,t,sum;
  while(scanf("%s",&s)!=EOF)
  {
  	t=0;
  	sum=0;
  	f1=f2=f3=f4=1;
  	memset(ans,0,sizeof(ans));
  	num=0;
  	l=strlen(s);
  	for(i=0;i<l;i++)
  	if(s[i]=='0')num++;
  	for(i=0;i<l;i++)
  	{
  		if(s[i]=='0')continue;
	  	if(s[i]=='1'&&f1)
		  {f1--;continue;}	
		  if(s[i]=='6'&&f2){
  			f2--;
  			continue;
  		}
  		if(s[i]=='8'&&f3){
		  	f3--;
		  	continue;
		  }
		  if(s[i]=='9'&&f4){
  			f4--;
  			continue;
  		}
  		ans[t++]=s[i];
  		sum=(sum*10+s[i]-'0')%7;
	  	}
	  	printf("%s",ans);
	  	if(sum==0)printf("%s",ap[0]);
	  	if(sum==1)printf("%s",ap[3]);    //1*10000+y
	  	if(sum==2)printf("%s",ap[6]);
		if(sum==3)printf("%s",ap[2]);
		if(sum==4)printf("%s",ap[5]);
		if(sum==5)printf("%s",ap[1]);
		if(sum==6)printf("%s",ap[4]);
		for(i=0;i<num;i++)   //尾部添加0
		printf("0");
		printf("\n");   
	  }
	  return 0;
  }	


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Codeforces 1806C题目链接:https://codeforces.com/problemset/problem/1806/C 题目描述: 给定一个长度为 $n$ 的整序列 $a_1,a_2,\dots,a_n$,你可以进行任意多次操作,每次操作可以选择一个区间 $[l,r]$,将区间内的所有加上 $1$ 或者减去 $1$。你的目标是使得序列中的所有都相等,求最小的操作次。 解题思路: 首先考虑对于一个来说,如何将它变成序列中的所有。由于每次操作可以将一个区间内的全部加上或减去 $1$,所以我们可以将该变成序列中的中位。中位是序列中所有排完序后处在中间的,如果序列长度为偶,则中位是中间两个的平均。 接下来考虑对于整个序列来说,如何将所有变成相等的。我们可以先将所有变成中位,然后计算每个与中位的差值之和,这个值就是最小的操作次。 最后考虑如何将一个变成中位。设序列长度为 $n$,$x$ 为中位,则有以下两种情况: - 当 $n$ 为奇时,$x=a_{\lfloor\frac{n+1}{2}\rfloor}$。 - 当 $n$ 为偶时,$x=\frac{a_{\frac{n}{2}}+a_{\frac{n}{2}+1}}{2}$。 对于第一种情况,我们可以将序列中所有先减去 $a_{\lfloor\frac{n+1}{2}\rfloor}$,然后再进行操作。 对于第二种情况,我们可以将序列中所有先减去 $\frac{a_{\frac{n}{2}}+a_{\frac{n}{2}+1}}{2}$,然后再进行操作。注意,当 $n=2$ 时,$\frac{n}{2}=1$,需要特判。 代码实现:

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值