3.解方程(equation.cpp/c/pas)【问题描述】已知多项式方程:a ! + a ! x + a ! x ! + ⋯ + a ! x ! = 0求这个方程在[1, m]内的整数解(n 和 m 均为正整数)。【输入】输入文件名为 equation.in。输入共 n+2 行。第一行包含 2 个整数 n、m,每两个整数之间用一个空格隔开。接下来的 n+1 行每行包含一个整数,依次为a ! , a ! , a ! , ... , a ! 。【输出】输出文件名为 equation.out。第一行输出方程在[1, m]内的整数解的个数。接下来每行一个整数,按照从小到大的顺序依次输出方程在[1, m]内的一个整数解。【输入输出样例 1】equation.in equation.out2 10 11 1-21【输入输出样例 2】equation.in equation.out2 10 22 1-3 21【输入输出样例 3】equation.in equation.out2 10 0132第 5 页共 6 页提高组 day2全国信息学奥林匹克联赛(NOIP2014)复赛【数据说明】对于 30%的数据,0 < n ≤ 2, a ! ≤ 100,a ! ≠ 0, m ≤ 100;对于 50%的数据,0 < n ≤ 100, a ! ≤ 10 !"" ,a ! ≠ 0,m ≤ 100;对于 70%的数据,0 < n ≤ 100, a ! ≤ 10 !"""" ,a ! ≠ 0,m ≤ 10000;对于 100%的数据,0 < n ≤ 100, a ! ≤ 10 !"""" ,a ! ≠ 0,m ≤ 1000000。
考场上想到了在同余系中枚举x,但是对于最后30%数据用的自然溢出,自然溢出很容易被卡掉。其实这种做法已经十分贴近正解了。观察发现,取质数p,对于解a,b,若a==b(mod p)那么他们带入算出的值一定相同,所以只用取多个较小p,预处理出[0,p-1]的值,在枚举[1,m]代入检验即可,bzoj数据很不良心啊,要么TLE,要么WA,jason_yu帮我检查了半天,才发现由于ans=(ans * i + a[ii][j])%pmod;我写成了{ans=(ans+x*a[j])%pmod;x=x*i%pmod;}常数过大,所以时限内尝试质数个数过少。
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cstdlib> using namespace std; #define PROB "equation" #define MAXN 1100001 #ifdef WIN32 #define LL "%I64d" #else #define LL "%lld" #endif typedef long long qword; const int mod[5] = {22861,22871,22877,22901,22907 }; int a[11][110]; bool ok[MAXN]; bool ok2[5][30000]; char s[10010]; int n,m; void work(); int main() { freopen(PROB".in","r",stdin); freopen(PROB".out","w",stdout); int ii,i,j, k; int x; scanf("%d%d\n",&n,&m); int ll = 4; for (ii=0;ii<=n;ii++) { // scanf("%s", s); fgets(s,sizeof(s),stdin); int l = strlen(s)-1; if((s[l-1]<'0' || s[l-1]>'9') && s[l-1]!='-')l--; for(int j = 0; j < ll; j ++){ int pmod = mod[j]; a[j][ii] =0; x=1; k=0; if (s[k]=='-')k++,x=-x; else if (s[k]=='+')k++; for (;k<l;k++) { a[j][ii]=(a[j][ii]*10+s[k]-'0')%pmod; } a[j][ii]=a[j][ii]*x%pmod; if(a[j][ii] < 0) a[j][ii] += pmod; } } memset(ok,1,sizeof(ok)); memset(ok2,1,sizeof(ok2)); int pmod; int ans; for (ii=0;ii<ll;ii++) { pmod=mod[ii]; for (i=0;i<pmod;i++) { ans=0; for (j=n;j>=0;j--) { ans=(ans * i + a[ii][j])%pmod; } if (ans) { ok2[ii][i]=false; } } } int cnt = 0; for (int i=1;i<=m && cnt <= n;i++) { for (int j=0;j<ll;j++) { if (!ok2[j][i%mod[j]]){ ok[i]=false; break; } } if(ok[i]) ++ cnt; } printf("%d\n",cnt); for (i=1;i<=m;i++) if (ok[i]) printf("%d\n",i); return 0; }
转载于:https://www.cnblogs.com/mhy12345/p/4109764.html