Loading

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

题意

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

思路

由莫比乌斯函数的性质可以发现\(x≡0\pmod{4}\)的莫比乌斯函数为\(0\),对\(9\)\(25\)\(49\)\(121\)\(169\)同理,所以可以通过判断\(200\)个数中\(0\)的情况,可以取得一个第一个数的备选集(\(x≡a_1\pmod{4}\)\(x≡a_2\pmod{9}\)\(x≡a_3\pmod{25}\)\(x≡a_4\pmod{49}\)\(x≡a_5\pmod{121}\)\(x≡a_6\pmod{169}\),可以通过中国剩余定理算出),然后对\(x_1\dots 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\n";
        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<<"\n";
        else
            cout<<"-1\n";
    }
    else
        cout<<"-1\n";
}

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

    return 0;
}

posted @ 2021-04-06 14:25  intmian  阅读(111)  评论(0编辑  收藏  举报