noip2014 提高組題解 equation

2021-06-27 00:28:37 字數 2569 閱讀 5503

題目大意:

給定高次方程an*x^n+...+a1*x^1+a0=0 求[1,m]區間內有多少個整數根

ai<=10^10000,m<=1000000,n<=100

首先,在考試的時候由於我很弱,一看到ai的範圍我就傻了,果斷30分騙起

解題思路:

1.30分

30分很好騙,直接暴力就行了

2.60分

因為我考試的時候寫的是30分,我也沒去寫60分,聽說好像高精度壓位然後暴力可以,我也不知道是不是真的,但是估計差不多,可能要用到秦九韶/霍納法則優化(就是用線性的時間求出對於乙個x方程的值,不會的請自己查閱)我覺得沒必要研究這個60分寫法

3.100分

(反正我考試的時候想不出來)但是我們學校有乙個人想出來了orz首先我們要知道乙個性質,對於乙個高次方程的係數取模,設取模的數為k,假設我們令之後的式子左邊為f(x),那麼原方程的解x0一定滿足f(x0%k)%k=0。證明的話就不提供了,請讀者自己查閱(其實是我不會)。

所以我們只需要隨機乙個質數k,然後對原方程的係數取模(一位一位的讀,操作第i位時需要把前面的操作得到的數乘以10然後加上第i位與1或-1乘積的後再取模k),取模之後的方程必須滿足存在取模後的係數不為0,如果取模後係數都為0,就無意義了,如果隨機到的質數使所有的係數都為0,那麼請重新隨機k

之後我們從1~min(k,m)中列舉對於取模後的方程f'滿足f'(x)%k=0的x,之後將每乙個得到的數加上k的t倍(k*t要小於m),顯然這些也滿足f'(x)%k=0,這樣我們就可以求出包含所有原方程解的一些數(顯然這些數有些不是原方程的解,只是取模後。。。。。),我們稱之為當前的解

然後在不斷的隨機質數w對方程的係數取模,然後將當前的解再帶入新的取模方程中判斷f''(x)%w=0,如果不滿足,就將其踢出當前的解,我們發現,如果是原方程的解,無論怎樣,都不會被這樣篩選掉

當然,不斷的篩選需要卡時,當你篩選的時間達到900ms是就直接break,這樣基本(其實就是幾乎100%)上就是答案了。

乙個比較重要的問題就是質數的選擇,如果選擇的質數k太大,那麼在第一次尋找當前的解時,將會出現k過大使得時間複雜度達到o(kn),當k過大時就會超時,如果k太小那麼就會出現資料將範圍內的所有質數乘起來使得你不管怎麼找都找不到滿足要求的k,這樣你就滾大粗了。所以找到乙個合適的質數是必要的。我覺得可以選擇在10000~100000之間的質數,因為把所有的乘起來比10^10000大,沒法使得無論你怎麼找都方程係數全部為0

解決了前面乙個問題之後,還要選擇質數w,如果質數w過小,那麼將無法篩去錯解,如果w過大。。。。。我也不知道會怎樣。

反正我取的還是10000~100000間的(為了偷懶不想再篩一遍質數),反正基本上不會出錯,但是我建議大家不要學我,盡量選擇10^6~10^7之間的數

經過測試,極限資料大概可以隨機w篩選200餘次,基本上不會錯(如果還錯的話。。。。。。請去買彩票。。。。。。。。。)

對於篩素數,我推薦大家去用線性的尤拉篩,因為畢竟10^7比較大,如果準備像我一樣的請忽視。。。。。。。。。。。。

下面附上我修改後水過民間資料的程式(寫得醜不要吐槽...........變數名請不要吐槽。。。。)

//本人是淳樸的c黨

#include #include #include #include #include #define max(a,b) (a>b?a:b)

#define min(a,b) (a>b?b:a)

int n,m;

int moda[11000]=;

int ans[10100]=;

int ansp=0;

char a[110][10010]=;

int len[110]=;

int hash[100010]=;

int f[1000010]=;

int zs[10000]=;

int zss=0;

int mod;

int main()

for(i=2;i<=100000;i++) }

for(;;)

else moda[i]=(moda[i]*10+k*(a[i][j-1]-'0'))%mod;

}if(moda[i]!=0)

p++;

} if(p>0)

break; }

for(i=1;i<=mod && i<=m;i++)

for(i=1;i<=ansp;i++)

for(t=1;clock()<=900;t++)

else moda[i]=(moda[i]*10+k*(a[i][j-1]-'0'))%mod;

}if(moda[i]!=0)

p++;

}if(p>0)

break;

} p=ansp;

ansp=0;

for(i=1;i<=p;i++)

}printf("%d\n",ansp);

for(i=1;i<=ansp;i++)

printf("%d\n",ans[i]);

fclose(stdin);

fclose(stdout);

return 0;

}

noip2014 提高組題解 link

題目描述 聯合權值 link.cpp c pas 問題描述 無向連通圖g 有n 個點,n 1 條邊。點從1 到n 依次編號,編號為 i 的點的權值為w i 每條邊的長度均為1 圖上兩點 u v 的距離定義為u 點到v 點的最短距離。對於圖g 上的點對 u,v 若它們的距離為2 則它們之間會產生wu ...

NOIP2014提高組 尋找道路

noip2014 提高組 day2 試題。在有向圖 g 中,每條邊的長度均為 1,現給定起點和終點,請你在圖中找一條從起點到終點的路徑,該路徑滿足以下條件 1 路徑上的所有點的出邊所指向的點都直接或間接與終點連通。2 在滿足條件 1 的情況下使路徑最短。注意 圖 g 中可能存在重邊和自環,題目保證終...

NOIP2014提高組 解方程

noip2014 提高組 day2 試題。已知多項式方程 a0 a1 x a2 x2 an xn 0 求這個方程在 1,m 內的整數解 n 和 m 均為正整數 輸入共 n 2 行。第一行包含 2 個整數 n m,每兩個整數之間用乙個空格隔開。接下來的 n 1 行每行包含乙個整數,依次為 a0,a1,...