[NOIP2014] 解方程

題目描述

已知多項式方程:ios

\[a_0+a_1x+a_2x^2+⋯+a_nx^n=0\]數組

求這個方程在 [1,m] 內的整數解(n 和 m均爲正整數)。spa

輸入輸出格式

輸入格式:code

共 n+2行。ci

第一行包含 2 個整數 n,m,每兩個整數之間用一個空格隔開。string

接下來的 n+1行每行包含一個整數,依次爲 a0,a1,a2…an。io

輸出格式:class

第一行輸出方程在 [1,m] 內的整數解的個數。stream

接下來每行一個整數,按照從小到大的順序依次輸出方程在 [1,m] 內的一個整數解。im

輸入輸出樣例

輸入樣例#1:

2 10
1
-2
1

輸出樣例#1:

1
1

輸入樣例#2:

2 10
2
-3
1

輸出樣例#2:

2
1
2

輸入樣例#3:

2 10
1
3
2

輸出樣例#3:

0

說明

對於 30% 的數據:\(0<n≤2,∣a_i∣≤100,a_n≠0,m<100\).
對於 50% 的數據:\(0<n≤100,∣a_i∣≤10^{100},a_n≠0,m<100\)
對於 70% 的數據:\(0<n≤100,∣a_i∣≤10^{10000},a_n≠0,m<10^4\)
對於 100% 的數據:\(0<n≤100,∣a_i∣≤10^{10000},a_n≠0,m<10^6\)

Solution

首先咱們得明白一條性質,若是咱們選一個質數p,若是枚舉x,發現多項式結果ans%p≠0,那麼咱們就能確定x不是解,由於若是是解,那麼多項式答案應該爲0,可是0模任何數(除0以外)都爲0,而此時發現模p不等於0,那麼顯然x不是解,看一波複雜度,O(NM)貌似能夠過70分。繼續想,
既然x不是解那麼顯然x+p也不是解,這樣問題就解決了。
prime[i],表明第i個質數是什麼。
可是又不能枚舉去篩,那複雜度又上去了,因此能夠用數組存下來,\(vis[i][j]\)表明i這個數取模第j個質數不等於0,那麼到時枚舉解x時,只需判斷\(vis[x~~mod ~~prime[j]][j]\)是否等於0就好了,爲了怕出錯,多選幾個質數就好了。
本題數據範圍這麼大,有點操蛋,這是要寫高精度的節奏,死活不打。
發現能夠一邊讀入一邊取模。
這題數據有點強,卡1~200全部質數,因此我就選了一千多的質數。
代碼:

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
typedef unsigned long long ll;
char s[101][10010];
ll prime[]={2,7,9,11,103,1597,1601,1607,1609,1613,1619,1621,1627};
ll real[1010000],kzj=0;
ll p[110][20],vis[120][20];
ll ans[1001010];
ll check(char *ss,ll mod)
{
    ll flag=1,tot=0,x=0;char ch=ss[0];
    ll len=strlen(ss);
    if(ch<'0'||ch>'9') if(ch=='-') flag=-1,tot++,ch=ss[1];
    while(ch<='9'&&ch>='0') 
    {
        x=((x*10)%mod+(ch-48))%mod;
        ch=ss[++tot];
        if(tot==len)
        break;
    }
    return (x*flag+mod)%mod;
}
int main()
{   
//  freopen("xuanxue.in","r",stdin);
//  freopen("xuanxue.out","w",stdout);
    ll n,m;
    cin>>n>>m;
    n++;
    for(ll i=1;i<=n;i++)
    scanf("%s",s[i]);
    for(ll i=1;i<=n;i++)
    {
        for(ll j=0;j<=12;j++)
        p[i][j]=check(s[i],prime[j]);
    }
    for(ll i=1;i<=1700;i++)
    {
        ll flag=0;
        for(ll j=0;j<=12;j++)
        {
            ll k=1,sum=0;
            ll mod=prime[j];
            for(ll t=1;t<=n;t++)
            {
                sum=(sum%mod+p[t][j]%mod*k%mod)%mod;    
                k=k*i%mod;
            }
            if(sum!=0) 
            {
                vis[i][j]=1;
            }
        }
    }
    for(ll i=1;i<=m;i++)
    {
        ll flag=0;
        for(ll j=0;j<=12;j++)
        if(vis[i%prime[j]][j]==1)
        flag=1;
        if(!flag) real[++kzj]=i;
    }
    cout<<kzj<<endl;
    for(ll i=1;i<=kzj;i++)
    printf("%lld\n",real[i]);
}
相關文章
相關標籤/搜索