您的位置:首页 > 其它

刷题记录-P2312 解方程

2017-09-18 00:42 183 查看
题目链接:https://www.luogu.org/problem/show?pid=2312

这题一开始是这么考虑的:如果f(x)!=0,那么f(x)%k一定也不等于0

这样可以进行检验,选取若干个k使得解的范围缩小,

最后用高精度一一进行验证。

70分

#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cstring>
#include<vector>
#define MAXN 105
#define SIZE 10025
#define MAXM 1000005
#define ll long long
using namespace std;
struct BigInt{
int len;
int s[SIZE];
int p; //p==1 + p==-1 -
BigInt(){
p=1;len=0;
memset(s,0,sizeof(s));
}
BigInt operator = (const char A[]){
int L=strlen(A);
len=L;
if('-'==A[0]){
p=-1; len--;
}
else{
p=1;
}
memset(s,0,sizeof(s));
for(int i=1;i<=len;i++){
s[i]=A[L-i]-'0';
}
return *this;
}
BigInt operator = (const BigInt &A){
len=A.len;
p=A.p;
memset(s,0,sizeof(s));
for(int i=1;i<=len;i++){
s[i]=A.s[i];
}
return *this;
}
BigInt operator *= (const int &A){
for(int i=1;i<=len;i++){
s[i]*=A;
}
for(int i=1;i<=len;i++){
s[i+1]+=s[i]/10; //+= not +
s[i]%=10;
}
int t=len;
while(s[t+1]){
t++;
s[t+1]+=s[t]/10;
s[t]%=10;
}
len=t;
return *this;
}
// compare Abs
bool operator < (const BigInt &A){
if(len!=A.len){
return (len<A.len);
}
for(int i=len;i>=1;i--){
if(s[i]!=A.s[i]){
return (s[i]<A.s[i]);
}
}
return 0;
}
BigInt operator -= (const BigInt &A){
BigInt B,C;
B=*this; C=*this;
if(B<A){
B.p=A.p;
B=A;
}
else{
B.p=p;
C=A;
}
for(int i=1;i<=C.len;i++){
B.s[i]-=C.s[i];
}
for(int i=1;i<=C.len;i++){
if(B.s[i]<0){
B.s[i]+=10;
B.s[i+1]-=1;
}
}
int t=C.len;
while(B.s[t+1]<0){
t++;
B.s[t]+=10;
B.s[t+1]-=1;
}
for(int i=B.len;i>=1;i--){
if(!B.s[i]){
B.len--;
}
else{
break;
}
}
if(!B.len) B.len=1;
return (*this=B);
}
BigInt operator += (const BigInt &A){
if(p*A.p<0){
return (*this-=A);
}
len=max(len,A.len);
for(int i=1;i<=len;i++){
s[i]+=A.s[i];
}
for(int i=1;i<=len;i++){
s[i+1]+=s[i]/10;
s[i]%=10;
}
if(s[len+1]){
len++;
s[len+1]=s[len]/10;
s[len]%=10;
}
return *this;
}
int operator % (const int &A){
int q=0;
for(int i=len;i>=1;i--){
q=q*10+s[i];
q=q%A;
}
return q*p;
}
void Print(){
if(p<0) printf("-");
for(int i=len;i>=1;i--){
printf("%d",s[i]);
}
printf("\n");
}
};
BigInt a[MAXN];
int prime[6]={0,1000193,1000367,1000427,1000453};
int n,m;
int b[MAXM];
int B[MAXN];
vector<int> ans,bans;
void read(int k){
char s[SIZE]={0};
int len=0;
char c=getchar();
do{
s[len++]=c;
c=getchar();
}while('0'<=c&&c<='9');
a[k]=s;
}
bool check(int k){
BigInt sum;
for(int i=n;i>=0;i--){
sum*=k;
sum+=a[i];
}
if(1==sum.len&&!sum.s[1]){
return 1;
}
return 0;
}
int main()
{
// freopen("T1.in","r",stdin);
// freopen("my.out","w",stdout);
scanf("%d%d",&n,&m);
getchar();
for(int i=0;i<=n;i++){
read(i);
}
for(int k=1;k<=4;k++){
for(int i=0;i<=n;i++){
B[i]=a[i]%prime[k];
}
for(int x=1;x<=m;x++){
ll sum=0;
for(int i=n;i>=0;i--){
sum=((sum*x)+B[i])%(ll)prime[k];
}
if(sum){
b[x]=-1;
}
else if(b[x]!=-1){
b[x]=1;
}
}
}
for(int i=1;i<=m;i++){
if(1==b[i]){
bans.push_back(i);
}
}
for(int i=0;i<bans.size();i++){
if(check(bans[i])){
ans.push_back(bans[i]);
}
}
printf("%d\n",ans.size());
for(int i=0;i<ans.size();i++){
printf("%d\n",ans[i]);
}
return 0;
}这题AC解法是利用类似线性筛数的思想,

如果f(x)!=0那么f(x+kMOD)!=0(这个和我的想法是一致的)

关键就在于,我们可以利用这条性质,只处理0~MOD-1的部分

然后对于x,直接对MOD取模,然后就很大程度上减少了计算量
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cstring>
#include<vector>
#define MAXN 105
#define SIZE 10025
#define MAXM 1000005
#define ll long long
using namespace std;
const int prime[]={10007,10917,30071};
int n,m;
int a[MAXN][4];
bool f[MAXM][4];
char s[SIZE];
vector<int> ans;
bool calc(int x,int j){
ll sum=0;
for(int i=n;i>=0;i--){
sum=(sum*x+a[i][j])%prime[j];
}
return (0==sum);
}
int main()
{
//	freopen("T1.in","r",stdin);
//	freopen("my.out","w",stdout);
scanf("%d%d",&n,&m);
for(int i=0;i<=n;i++){
memset(s,0,sizeof(s));
scanf("%s",s);
int len=strlen(s),be=0;
int p=1;
if('-'==s[0]){
p=-1;
be++;
}
for(int j=0;j<3;j++){
ll temp=0;
for(int k=be;k<len;k++){
temp=((temp*10)+s[k]-'0')%prime[j];
}
a[i][j]=temp*p;
if(a[i][j]<0) a[i][j]+=prime[j];
}
}
for(int j=0;j<3;j++){
for(int i=0;i<prime[j];i++){
f[i][j]=calc(i,j);
}
}
for(int i=1;i<=m;i++){
int ok=1;
for(int j=0;j<3;j++){
if(!f[i%prime[j]][j]){
ok=0;
break;
}
}
if(ok){
ans.push_back(i);
}
}
printf("%d\n",ans.size());
for(int i=0;i<ans.size();i++){
printf("%d\n",ans[i]);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: