洛谷 2312 / bzoj 3751 解方程——取模

题目:https://www.luogu.org/problemnew/show/P2312

   https://www.lydsy.com/JudgeOnline/problem.php?id=3751

惭愧……先听了同学讲它,又看了题解,才A。

取一些模数就能限制时间复杂度并有一些概率正确。取模后常数也能取模,就不用高精度了!而且m以内的数只用算 0~模数-1 的值,表示取模后是该值的数在模该值意义下答案是否为0。

bzoj上的数据需要精心选取模数。据说2e4左右的效果最好?试了几次终于A了。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=105,M=1e4+5,A=1e6+5,K=15,C=7,D=4e4+5;
int n,m,a[N][M],nm[N],c[N],ans[A],cnt;
bool fx[N],flag;
int zs[K]={15671,29501,18919,16843,23767,30271,24443};
bool vis[K][D];
void solve(int p)
{
    for(int i=0;i<=n;i++)
    {
        c[i]=0;
        for(int j=1;j<=nm[i];j++) c[i]=(c[i]*10+a[i][j])%p;
        if(fx[i]) c[i]=(-c[i]+p)%p;
    }
}
void calc(int bh,int x,int p)
{
    int cr=0;
    for(int i=n;i>=0;i--)
        cr=(cr*x%p+c[i])%p;
    vis[bh][x]=(!cr);
}
int main()
{
    scanf("%d%d",&n,&m); char ch=getchar();
    for(int i=0;i<=n;i++)
    {
        while(ch>'9'||ch<'0'){ if(ch=='-') fx[i]=1; ch=getchar();}
        while(ch>='0'&&ch<='9') a[i][++nm[i]]=ch-'0',ch=getchar();
    }
    for(int i=0;i<C;i++)
    {
        solve(zs[i]);
        for(int j=0;j<zs[i]&&j<=m;j++)
            calc(i,j,zs[i]);
    }
    for(int i=1;i<=m;i++)
    {
        flag=0;
        for(int j=0;j<C;j++)
            if(!vis[j][i%zs[j]]) {flag=1;break;}
        if(!flag) ans[++cnt]=i;
    }
    printf("%d\n",cnt);
    for(int i=1;i<=cnt;i++) printf("%d\n",ans[i]);
    return 0;
}

 

posted on 2018-09-12 17:11  Narh  阅读(218)  评论(0编辑  收藏  举报

导航