NYOJ--1086是否被整除

             是否被整除

时间限制:1000 ms  |  内存限制:65535 KB
难度:2
描述
一个位数不大于100万位的正整数,如果它既能被11整除又能被2的n次方整除就输出YES否则输出NO
输入
输入有多组数据每组数据有两行
第一行一个n代表2的n次方(0<n<18)
第二行一个整数
输出
输出只有一行每行一个YES或NO
样例输入
1
110
2
1100
3
110
样例输出
YES
YES
N

暴力会超时:

   其实此题有规律:

 能被2的N次方的数整除的数的特征
 如果一个数末N位能被2的N次方的数整除,那么这个数就能被2的N次方的这个数整除。
如能被8(2的3次方)整除的数的特征:这个数字的末三位能被8整除。
能被11整除的数的特征   
把一个数由右边向左边数,将奇位上的数字与偶位上的数字分别加起来,再求它们的差,如果这个差是11的倍数(包括0),那么,原来这个数就一定能被11除.   
 例如:判断491678能不能被11整除.   
 —→奇位数字的和9+6+8=23    
 
 —→偶位数位的和4+1+7=12  
 23-12=11  因此,491678能被11整除.  这种方法叫"奇偶位差法". 

参考代码:

<span style="font-family:Microsoft YaHei;">/**************
NYOJ 1086
Times:136ms
#include<stdio.h>
#include<string.h>
char str[10000005];
int fun()
{
    int i,sum=0,len=strlen(str);
    for(i=0; i<len; i++)
    {
        if(i%2) sum+=(str[i]-'0');
        else sum-=(str[i]-'0');
    }
    if(sum%11==0)
        return 1;
    else return 0;
}
int gun(int n)
{
    int i,len=strlen(str);
    long long sum=0,a=1;
    for(i=0; i<n; i++)
        a*=2;
    for(i=len-n; i<len; i++)
        sum=sum*10+str[i]-'0';
    if(sum%a==0)
        return 1;
    else return 0;
}
int main()
{
    int n;
    while(scanf("%d%s",&n,&str)!=EOF)
    {
        if(fun()&&gun(n))
            printf("YES\n");
        else  printf("NO\n");
    }
    return 0;
 }</span>
学长的代码:
<span style="font-family:Microsoft YaHei;">#include<stdio.h>
#include<cstring>
using namespace std;
char s[1000005];
int main()
{
    int n;
    while(~scanf("%d%s",&n,s))
    {
        int t=strlen(s);
        long long int c=(1<<n)*11,sum=0;
        for(int i=0; i<t; i++)
            sum=(sum*10+s[i]-'0')%c;
        printf(sum?"NO\n":"YES\n");
    }
    return 0;
}
</span>

<span style="font-family:Microsoft YaHei;">    long long int c=(1<<n)*11,sum=0;表示2的n 次方,用了<<位运算,</span>



你可能感兴趣的:(ACM,数学题,nyoj)