1095. Nikifor 3
Time limit: 1.0 second
Memory limit: 64 MB
Memory limit: 64 MB
Nikifor knows that a certain positive integer has in its decimal form each of the digits 1,2,3,4. You are asked to determine if Nikifor can rearrange the digits of the number in such a way that the new number divides by 7.
Input
The first line contains the number
N (not exceeding 10000) of positive integers that are to be checked. The next
N lines contain these integers. Each number has no more than 20 digits.
Output
For each of the
N numbers output a number divisible by 7 that can be obtained from the corresponding number from the input data by a rearrangement of the digits. If such rearrangement does not exist you should output 0 in the corresponding line. In the case of several valid rearrangements you may find only one of them.
Sample
input | output |
---|---|
2 1234 531234 | 4123 354123 |
Problem Author: Dmitry Filimonenkov
题意:给你N个正整数,它们都含有数码1、2、3、4,不超过20位,要求你调整每个正整数中数字的顺序,使它能被7整除。
最朴素的做法,暴搜它的每一种排列,但20位就挂了,肯定TLE。
注意题目中有条件每个正整数都有1,2,3,4,所以应该好好利用这个条件才对。
那么我们可以把1,2,3,4各取出一个,会发现它们组成的四位数模7的余数有7种。
我取了这样一组数4123,1324,4321,2341,1432,2413,4213,它们模7分别余0,1,2,3,4,5,6
剩下的数码随便排列就可以了(0放最后),用这7个数填补其它数码组成的数字模7剩余的部分即可。
最朴素的做法,暴搜它的每一种排列,但20位就挂了,肯定TLE。
注意题目中有条件每个正整数都有1,2,3,4,所以应该好好利用这个条件才对。
那么我们可以把1,2,3,4各取出一个,会发现它们组成的四位数模7的余数有7种。
我取了这样一组数4123,1324,4321,2341,1432,2413,4213,它们模7分别余0,1,2,3,4,5,6
剩下的数码随便排列就可以了(0放最后),用这7个数填补其它数码组成的数字模7剩余的部分即可。
以上参考别人的思路。
思路已经很清晰了。。。
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include<cstring>
#include <algorithm>
#include <math.h>
using namespace std;
int res[]={4123,1324,4321,2341,1432,2413,4213};
int c[10];
int main()
{
char ch[25];
int cas;
int i,j,len;
scanf("%d",&cas);
while(cas--)
{
memset(c,0,sizeof(c));
scanf("%s",ch);
len=strlen(ch);
for(i=0;i<len;i++)
{
c[ch[i]-'0']++;
}
c[1]--;c[2]--;c[3]--;c[4]--;
int cnt=0;
long long num=0;
for(i=1;i<10;i++)
{
if(c[i])
{
for(j=0;j<c[i];j++)
{
cout<<i;
cnt++;
num*=(long long)10;
num+=(long long)i;
// num%=7;
}
}
}
int tmp=num%7; // ????????????????
tmp*=10000;
tmp%=7;
if(tmp==0)
cout<<res[0];
else
cout<<res[7-tmp];
if(cnt+4<len)
{
for(i=cnt+4+1;i<=len;i++)cout<<"0";
}
cout<<endl;
// cout<<num<<endl;
}
}
刚开始自己写的老师WA2,然后就看自己和别人的代码的区别,发现自己sum取余的时候弄错了,因为sum是除去1234之后剩下的,所以要乘上10000,然后再取余才能是结果。( 刚开始还想不明白。。。真是醉了,还是神牛告诉我的当然要乘以10000辣。。。。。。)就是(sum*10000+1234(的组合))%7==0 那么,sum*10000的取余7的结果加上1234组合取余7的结果为0,同时sum*10000%7==( ( sum%7)*10000)%7 因为sum*10000会超出long long 的取值范围。这是一个数学公式
如果a%b=c,那么(a*k)%b=a%b+a%b+…+a%b=c+c+…+c=kc(k>0)
另外别人的做法是,每次sum+=(sum*10+i)%7 然后计算 (sum*10000)%7 结果是一样的。
另外关于取余,想到了中国剩余定理,所以就写一下吧,博客里也没有写到过。
中国剩余定理 ,首先要从一个古老的数学题开始
在《孙子算经》中有这样一个问题:“今有物不知其数,三三数之剩二(除以3余2),五五数之剩三(除以5余3),七七数之剩二(除以7余2),问物几何?”这个问题称为“孙子问题”
那么我们首先假设满足除3余2的数为n1,满足除5余3的是n2,满足除7余2的是n3
那么由a%b==c那么(a+kb)%b==c这个公式,我们知道若想(n1+n2+n3)%3==2就要n2,n3 是3的倍数,同理(n1+n2+n3)%5==3 n1,n3是5的倍数,(n1+n2+n3)%7==2,n1,n2是7的倍数,所以,
- n1除以3余2,且是5和7的公倍数。
- n2除以5余3,且是3和7的公倍数。
- n3除以7余2,且是3和5的公倍数。所以他的本质就是 从5和7的公倍数中找除3余2的+从3和7的公倍数中找除5余3的+从3和5的公倍数中找除7余2 。。那么找数字的时候也可以用到上面得公式 找除3余2的就可以找除3余1的然后乘以2,最后可能这个结果不是最小的,然后可以处以3和5和7的最小公倍数,答案就是最小的。
大概就是这些了,另外附上一些大神门关于除7取余的经典解法
Matrix67大神的博客
一位有趣的大神的博客
http://hi.baidu.com/curioz/item/27812e32fdb8bb149dc65eda 这个里面还有很多好玩的链接,(*^__^*) 嘻嘻……