gym102056C Heretical … Möbius(2018-2019 ACM-ICPC, Asia East Continent Finals)中国剩余定理

题意

给一个长度为(200)(01)串,判断是否是序列({x_i | x_i=|mu(i)|,1le ile10^9})的一部分。若是,输出开头数字的最小值。

思路

由莫比乌斯函数的性质可以发现(x≡0pmod{4})的莫比乌斯函数为(0),对(9)(25)(49)(121)(169)同理,所以可以通过判断(200)个数中(0)的情况,可以取得一个第一个数的备选集((x≡a_1pmod{4})(x≡a_2pmod{9})(x≡a_3pmod{25})(x≡a_4pmod{49})(x≡a_5pmod{121})(x≡a_6pmod{169}),可以通过中国剩余定理算出),然后对(x_1dots x_{200})每个数判断是否是正确的莫比乌斯函数值

代码

#include<bits/stdc++.h>
using namespace std;
using ll=long long;
int mod[6]={4,9,25,49,121,169};
const ll M=901800900;

ll mpow(ll a,ll b,ll mod)
{
    ll ans=1;
    while(b)
    {
        if(b&1)ans=ans*a%mod;
        a=a*a%mod;
        b>>=1;
    }
    return ans;
}

int crt(int a[6])
{
    int ans=0;
    for(int i=0;i<6;i++)
    {
        ll m=M/mod[i];
        ll m1=mpow(m,mod[i]*mod[i]-mod[i]-1,mod[i]);
        ans=(ans+a[i]*m*m1)%M;
    }
    return ans;
}

string str;
const int maxp=1e9-199;
vector<int>p[6];
int re[6];
ll ans=1e9;

const int maxn=4e4+5;
int prime[maxn],pcnt;
void init(int n=maxn-1)
{
    for(int i=2;i<=n;i++)
    {
        if(!prime[i])
            prime[++pcnt]=i;
        for(int j=1;j<=pcnt,prime[j]*i<=n;j++)
        {
            prime[prime[j]*i]=1;
            if(i%prime[j]==0)
                break;
        }
    }
}

int absu(int x)
{
    for(int i=1;i<=pcnt;i++)
    {
        int pp=prime[i]*prime[i];
        if(pp>x)
            break;
        if(x%pp==0)
            return 0;
    }
    return 1;
}

bool check(int p)
{
    vector<int>ans(200,1);
    for(int i=1;i<=pcnt;i++)
    {
        int pp=prime[i]*prime[i];
        for(int j=(prime[i]-1+p)/prime[i]*prime[i];j<p+200;j+=prime[i])
        {
            if(j%pp==0)
                ans[j-p]=0;
        }
    }
    for(int i=0;i<200;i++)
    {
        if(ans[i]!=str[i]-'0')
            return false;
    }
    return true;
}

void dfs(int i)
{
    if(i<0)
    {
        ll p=crt(re);
        while(p<=maxp)
        {
            if(check(p))
            {
                ans=min(ans,p);
                break;
            }
            p+=M;
        }
        return;
    }
    for(int x:p[i])
    {
        re[i]=x;
        dfs(i-1);
    }
}

void solve(){
    string tmp;
    str="";
    for(int i=0;i<10;i++)
    {
        cin>>tmp;
        str+=tmp;
    }
    int cnt=0;
    for(int i=0;i<200;i++)
        cnt+=str[i]-'0';
    if(cnt<100) //剪枝
    {
        cout<<"-1
";
        return;
    }


    bool has=true;
    for(int i=0;i<6;i++)
    {
        p[i].clear();
        for(int j=0;j<mod[i];j++)
        {
            bool flag=true;
            for(int k=j;k<200;k+=mod[i])
            {
                if(str[k]=='1')
                {
                    flag=false;
                    break;
                }
            }
            if(flag)
                p[i].push_back((mod[i]-j)%mod[i]);
        }
        if(p[i].empty())
            has=false;
    }
    if(has)
    {
        dfs(5);
        if(ans<(1e9))
            cout<<ans<<"
";
        else
            cout<<"-1
";
    }
    else
        cout<<"-1
";
}

int main()
{
    init();
    ios::sync_with_stdio(false);
    int T=1;
    // cin>>T;
    for(int i=1;i<=T;i++)
        solve();

    return 0;
}

原文地址:https://www.cnblogs.com/intmian/p/14621700.html