• 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;
    }
     
     
    人一我百!人十我万!永不放弃~~~怀着自信的心,去追逐梦想
  • 相关阅读:
    2019年面试题1
    面试题
    vsftp多个用户公享同一个文件,但是权限不同
    centos7搭建ftp
    安装v2ra y
    centos7安装lamp
    日升昌面试题
    一些插件
    面试被怼集(字节跳动篇)
    TOMCAT原理详解及请求过程(转载)
  • 原文地址:https://www.cnblogs.com/kuangbin/p/2976730.html
Copyright © 2020-2023  润新知