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;
}

 

 

 

   

    原文作者:算法小白
    原文地址: https://www.cnblogs.com/kuangbin/archive/2013/03/23/2976730.html
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞