HDU 2197 本原串 (数学)

本原串

Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 408    Accepted Submission(s): 129


Problem Description
由0和1组成的串中,不能表示为由几个相同的较小的串连接成的串,称为本原串,有多少个长为n(n<=100000000)的本原串?
答案mod2008.
例如,100100不是本原串,因为他是由两个100组成,而1101是本原串。
 

 

Input
输入包括多个数据,每个数据一行,包括一个整数n,代表串的长度。
 

 

Output
对于每个测试数据,输出一行,代表有多少个符合要求本原串,答案mod2008.
 

 

Sample Input
1
2
3
4
 

 

Sample Output
2
2
6
12
 

 

Author
scnu
 

 

Recommend
lcy
 
 
 
本题比较有意思的题目。
长度为n的01串的总数为2^n.要求本原串,只要总数减掉非本原串。
非本原串可以由本原串得到。
f[n]=2^n -  求和(f[i])  -2  其中i是n的大于等于2的约数。
 
找约数的时候,只要2到sqrt(n)枚举。因为找到一个i,那么n/i一定是约数了。
 
具体看代码吧。
 
/*

* G++ 0ms 336K

*/



#include <stdio.h>

#include <algorithm>

#include <iostream>

#include <iostream>

#include <string>

#include <map>

using namespace std;



const int MOD=2008;

map<int,int>mp;

int pow_m(int a,int n)

{

    int ret=1;

    int tmp=a%MOD;

    while(n)

    {

        if(n&1)

        {

            ret*=tmp;

            ret%=MOD;

        }

        tmp*=tmp;

        tmp%=MOD;

        n>>=1;

    }

    return ret;

}

int get(int x)

{

    if(mp[x]!=0)return mp[x];

    if(x==1)return mp[x]=2;

    int ans=pow_m(2,x);

    ans-=2;

    ans%=MOD;

    for(int i=2;i*i<=x;i++)

    {

        if(x%i!=0)continue;

        if(i*i==x)

        {

            ans-=get(i);

            ans%=MOD;

        }

        else

        {

            ans-=get(i);

            ans-=get(x/i);

            ans%=MOD;

        }

    }

    return mp[x]=(ans+MOD)%MOD;

}

int main()

{

    int n;

    while(scanf("%d",&n)==1)

    {

        printf("%d\n",get(n));

    }

    return 0;

}

 

 

 

 

 

代码二:

/*

*G++  15ms  360K

*/



#include <stdio.h>

#include <algorithm>

#include <iostream>

#include <iostream>

#include <string.h>

#include <map>

using namespace std;



const int MOD=2008;

int a[10010];

int pow_m(int a,int n)

{

    int ret=1;

    int tmp=a%MOD;

    while(n)

    {

        if(n&1)

        {

            ret*=tmp;

            ret%=MOD;

        }

        tmp*=tmp;

        tmp%=MOD;

        n>>=1;

    }

    return ret;

}

int get(int x)

{

    if(x<=10000&&a[x]!=0)return a[x];

    if(x==1)return 2;

    int ans=pow_m(2,x);

    ans-=2;

    ans%=MOD;

    for(int i=2;i*i<=x;i++)

    {

        if(x%i!=0)continue;

        if(i*i==x)

        {

            ans-=get(i);

            ans%=MOD;

        }

        else

        {

            ans-=get(i);

            ans-=get(x/i);

            ans%=MOD;

        }

    }

    return (ans+MOD)%MOD;

}

int main()

{

    int n;

    memset(a,0,sizeof(a));

    for(int i=1;i<=10000;i++)a[i]=get(i);

    while(scanf("%d",&n)==1)

    {

        printf("%d\n",get(n));

    }

    return 0;

}

 

 

 

 
 

你可能感兴趣的:(HDU)