题目链接:
http://codeforces.com/problemset/problem/248/B
题目大意:
给一个n,求最小的n位数,使这个数能同时被2,3,5,7整除。其中1<=n<=10^5.
解题思路:
分析知这个数个位一定为零,因为它要同时被2和5整除,而一个数是否能被7整除取决于该数去掉最后一位的数减去最后一位的数的2倍的差能否被7整除。所以只需看去掉最后一位的数能否被7整除,所以倒数第二位一定为0,1,2,3,4,5,6其中之一,然后再分析这个数能否被3整除,如果所有位数之和能被3整除,则直接得出结果,如果被3整除余1,则加14(能同时满足被3,7整除),如果被3整除余2,则加7,也能满足要求。
判断一个数能否被7整除,可以通过去掉最后一位后减去最后一位的2倍能否被7整除来判断,但考虑到本题的特殊性,中间有一连串的0,而10……0被7除的余数与零的个数有周期性规律left[0]=1,left[1]=3,left[2]=2,left[3]=6,left[4]=4,left[5]=5,.……再left[i]表示有中间有i个零除以7后的余数,连上倒数第二位要求能被7整除则sumleft[1]=4,sumleft[2]=1,sumleft[3]=5,sumleft[4]=2,sumleft[5]=6,sumleft[6]=3,sumleft[i]表示当前面余数为i时的倒数第二的数的值,这样凑后一定能被7整除。
详见代码:
#include <iostream>
#include<cstdlib>
#include<cstdio>
#include<cstring>
using namespace std;
int main()
{
int n;
int left[6]={1,3,2,6,4,5};
int sumleft[7]={0,4,1,5,2,6,3};
while(scanf("%d",&n)!=EOF)
{
if(n==1||n==2)
{
printf("-1\n");
continue;
}
a[1]=1;
for(int i=2;i<=n;i++)
a[i]=0; //初始化过程
int temp=(n-3)%6;
a[n-1]=sumleft[left[temp]]; //temp表示中间零的个数,sumleft[i]表示当前面余数为i时的最后一位数的值使数能被7整除
if((a[n-1]+1)%3==1)
{
a[n-1]+=4;
a[n-2]+=1;
if(a[n-1]>9)
{
a[n-1]-=10;
a[n-2]++;
}
}
else if((a[n-1]+1)%3==2)
{
a[n-1]+=7;
if(a[n-1]>9)
{
a[n-1]-=10;
a[n-2]++;
}
}
for(int i=1;i<=n;i++)
printf("%d",a[i]);
putchar('\n');
}
return 0;
}
--------------------------------------------------------------------------------
→Judgement Protocol