HDU 2197 本原串 (規律+快速冪)

Mr_Treeeee發表於2020-04-06

本原串

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


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
 


此題用反面情況求解,長度為n的串有2^n中,減去非本原串,非本原串肯定是由長度為v字串不斷重複u次得到的,那麼v必然是n的約數。

應該可以打表加快速度,但我懶得寫,可以ac。


#include <iostream>
#include <stdio.h>
#include <string.h>
using namespace std;
#define ll long long
const ll p = 2008;
ll qkm(ll base, ll mi)
{
    ll ans=1;
    while(mi)
    {
        if(mi&1) (ans=ans*base)%=p;
        mi>>=1;
        (base*=base)%=p;
    }
    return ans;
}
ll d(ll x)
{
    if(x==1) return 2;
    ll ans=qkm(2,x)-2;
    for(ll i=2;i*i<=x;i++)
    {
        if(x%i==0)
        {
            (ans=ans-d(i)+p)%=p;
            if(i*i!=x) (ans=ans-d(x/i)+p)%=p;
        }
    }
    return ans;
}

int main()
{
    ll n;
    while(~scanf("%lld",&n))
    {
        printf("%lld\n",d(n));
    }
    
}


相關文章