【NOIP2014】D2T3 解方程 equation

当年做的时候,写了两个小时半高精度,然后没写出来= =
醉都醉死了。。
然后没去管他。

忽然在浙江省选讲课的时候突然有了灵感。。← ←好神奇是不是。。

思路:
0与0同余
运用同余的性质,左式各个因子加法结果若为0,mod 一个数后的结果还是为0。然后多取几个质数试一试。
于是这样就可以拿70分。

最后三十分需要这样优化:
f(x+p)=f(x)!=0
若1~p之间有个数不行,则它+kp(k为整数)也不行。
就好像那个质数筛一样的原理,拿来剪枝。就AC了。

UOJ 670ms 30048kb 2.9kb
bzoj 8452 ms 71004 kb
(bzoj数据好变态的说。。。请换质数还有下面的循环
int p1=22861;
int p2=22871;
int p3=22877;
int p4=22901;

for (int i=1;i<23000;i++)
    for (int j=0;j<=1;j++) 
    {
        num[i][j][1]=power(i,j,p1);
        num[i][j][2]=power(i,j,p2);
        num[i][j][3]=power(i,j,p3);
        num[i][j][4]=power(i,j,p4);
    }
for (int i=1;i<23000;i++)
    for (int j=2;j<=n;j++) 
    {
        num[i][j][1]=(num[i][j-1][1]*i)%p1;
        num[i][j][2]=(num[i][j-1][2]*i)%p2;
        num[i][j][3]=(num[i][j-1][3]*i)%p3;
        num[i][j][4]=(num[i][j-1][4]*i)%p4;
    }

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <string>
#include <cstring>
#include <vector>
#include <ctime>
using namespace std;

class bign{
    public:
        bool fu;
        int a[10010];
        int len;
        bign() {memset(a,0,sizeof(a));}
}a[110];

int b[110];
int c[110];
int d[110];
int e[110];
int num[30000][110][5];

int n,m;
vector<int> v,v2,v3,v4,v5;

istream & operator >>  (istream & cin,bign & q)
{
    string d;
    cin>>d;
    if (d[0]!='-')
    {
        q.len=d.size();
        for (int i=0;i<q.len;i++) q.a[q.len-i]=d[i]-'0';
    }else 
    {
        q.len=d.size();
        for (int i=1;i<q.len;i++) q.a[q.len-i]=d[i]-'0';
        q.fu=1;
        q.len--;
    }
    return cin;
}

int operator % (const bign &q,const int w)
{
    int res=0;
    for (int i=q.len;i>=1;i--)
    {
        res=res*10+q.a[i];
        res%=w;
    }
    if (!q.fu) return res;else return -res;
}

int power(int n,int k,int mod)
{
    int q=1;
    while (k)
    {
        if (k&1) q=(q*n)%mod;
        n=(n*n)%mod;
        k>>=1;
    }
    return q;
}

int p1=9973;
int p2=9949;
int p3=9967;
int p4=9941;
bool flag[1000010];

int main()
{
    freopen("equation.in","r",stdin);
    freopen("equation.out","w",stdout);

    cin>>n>>m;
    for (int i=0;i<=n;i++) cin>>a[i];
    for (int i=0;i<=n;i++) b[i]=a[i]%p1;
    for (int i=0;i<=n;i++) c[i]=a[i]%p2;
    for (int i=0;i<=n;i++) d[i]=a[i]%p3;
    for (int i=0;i<=n;i++) e[i]=a[i]%p4;


    for (int i=1;i<10000;i++)
        for (int j=0;j<=1;j++) 
        {
            num[i][j][1]=power(i,j,p1);
            num[i][j][2]=power(i,j,p2);
            num[i][j][3]=power(i,j,p3);
            num[i][j][4]=power(i,j,p4);
        }
    for (int i=1;i<10000;i++)
        for (int j=2;j<=n;j++) 
        {
            num[i][j][1]=(num[i][j-1][1]*i)%p1;
            num[i][j][2]=(num[i][j-1][2]*i)%p2;
            num[i][j][3]=(num[i][j-1][3]*i)%p3;
            num[i][j][4]=(num[i][j-1][4]*i)%p4;
        }

    for (int i=1;i<=1000000;i++) flag[i]=1;

    for (int i=1;i<=m;i++)
    {
        if (!flag[i]) continue;
        if (flag[i])
        {
            int res=0;
            for (int j=0;j<=n;j++) 
            {
                res+=(b[j]*num[i%p1][j][1])%p1;
                res%=p1;
            }
            if (res!=0) 
            {
                flag[i]=0;
                int k=p1;
                while (k+i<=m)
                {
                    flag[k+i]=0;
                    k+=p1;
                }
            }
        }
        if (flag[i])
        {
            int res=0;
            for (int j=0;j<=n;j++) 
            {
                res+=(c[j]*num[i%p2][j][2])%p2;
                res%=p2;
            }
            if (res!=0) 
            {
                flag[i]=0;
                int k=p2;
                while (k+i<=m)
                {
                    flag[k+i]=0;
                    k+=p2;
                }
            }
        }
        if (flag[i])
        {
            int res=0;
            for (int j=0;j<=n;j++) 
            {
                res+=(d[j]*num[i%p3][j][3])%p3;
                res%=p3;
            }
            if (res!=0) 
            {
                flag[i]=0;
                int k=p3;
                while (k+i<=m)
                {
                    flag[k+i]=0;
                    k+=p3;
                }
            }
        }
        if (flag[i])
        {
            int res=0;
            for (int j=0;j<=n;j++) 
            {
                res+=(e[j]*num[i%p4][j][4])%p4;
                res%=p4;
            }
            if (res!=0) 
            {
                flag[i]=0;
                int k=p4;
                while (k+i<=m)
                {
                    flag[k+i]=0;
                    k+=p4;
                }
            }
        }
        if (flag[i]) v.push_back(i);
    }
    cout<<v.size()<<endl;
    for (int i=0;i<v.size();i++) cout<<v[i]<<endl;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值