NOIP2014解方程解题报告

原题见洛谷(https://www.luogu.org/problem/show?pid=2312
QWQ
好像有一个东西叫秦九韶算法~这个东西就是用来计算多项式值的一种方法能减少运算次数发一下百度百科的秦九韶算法的解释吧~不过这是高中数学的内容基本上上过高中的应该都知道吧TAT链接:(https://baike.baidu.com/item/秦九韶算法/449196?fr=aladdin)
这道题呢我们可以吧左边的当成多项式来算用秦九韶算法就行了啊~

inline bool qjs(long long x){
    sum=0;
    for(register int i=n;i>=0;i--){
        sum=((a[i]+sum)*x)%p;
    }
    return !sum;
}

下面的思路就是逐个从1~m枚举算式的值,只要这个算式的值是0就计数好了
先贴一下代码在讲解吧~嗷呜~

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

const int p=1000000007;
long long a[110],key[1000000];
bool t=true;
int ans=0,cnt,sum=0;
int n,m;

inline long long read(){
    long long sum=0,fg=1;
    char c=getchar();
    while(c<'0' || c>'9'){
        if(c=='-'){
            fg=-1;
        }
        c=getchar();
    }
    while(c>='0' && c<='9'){
        sum=((sum*10)+c-'0')%p;
        c=getchar();
    }
    return sum*fg;
}
inline void out(int x){
    if(x<0){
        putchar('-');
        x=-x;
    }
    if(x>9){
        out(x/10);
    }
    putchar(x%10+'0');
}
inline bool qjs(long long x){
    sum=0;//一定要清零
    for(register int i=n;i>=0;i--){
        sum=((a[i]+sum)*x)%p;
    }
    return !sum;
}

int main(){
    n=read();
    m=read();
    for(register int i=0;i<=n;i++){
        a[i]=read();
    }
    for(register int i=1;i<=m;i++){
        if(qjs(i)){
            t=false;
            ans++;
            cnt++;
            key[cnt]=i;
        }
    }
    if(t){
        out(ans);
        printf("\n");
        return 0;   
    }
    out(ans);
    printf("\n");
    for(register int i=1;i<=cnt;i++){
        out(key[i]);
        printf("\n");
    }
    return 0;
}

p是一个大的质数,防止爆int,可以记得读入优化的时候也膜一下,
然后呢read和out函数就是快速读入和快速输出啦~
bool t就是用t来判断是否有解。cnt来记录解的个数。sum来记录多项式的结果,记得在qjs函数里一定要把sum清零,否则就是10分,a数组就是来记录多项式系数的值的,key数组是用来记录每个解的值的
发一份有注释的题解:

#include<algorithm>
#include<iostream>
#include<iomanip>
#include<cstring>
#include<cstdio>
#include<cmath>
using namespace std;
typedef long long ll;
const int p=1000000007;//取模比较方便为
bool t=true;//用来判断是否有解 
int n,m,ans,cnt,sum=0;//cnt记录解的个数;sum用来计算多项式的结果 
int A[103],key[1000003];
//A[]记录式中的a0,a1,a2(注意是以0为起点)
//key记录每个解的值 
ll read(){//读入优化(似乎不加会T两个点w)
    ll sum=0,fg=1;
    char c=getchar();
    while(c < '0' || c > '9'){
        if(c=='-') fg=-1;//如果读到负号则记录 
        c=getchar();
    }
    while(c >='0' && c <='9'){
        sum=((sum*10)+c-'0')%p;
        //注意因为A[]可能很大,所以读入时就要进行取模操作 
        c=getchar();
    }
    return sum*fg;
    //如果是负数(fg==-1,即读到了负号)那么返回的值为负数 
}
void print(int x){//输出优化(这个可以不加)
    if(x<0){
        putchar('-');
        x=-x;
    }
    if(x>9){
        print(x/10);
    }
    putchar(x%10+'0');
}
bool calc(ll x){
    sum=0;//一定要清零!!!
    for(ll i=n;i>=0;i--){
        sum=((A[i]+sum)*x)%p;
        //这里套用秦九韶算法求多项式的值 
    }
    return !sum;//如果答案是0说明x值为该多项式的解,返回1(true) 
}
int main(){
    n=read();
    m=read();
    for(ll i=0;i<=n;i++){
        A[i]=read();
    }
    for(ll i=1;i<=m;i++){
        if(calc(i)){//如果返回的是1(true)则说明有解 

            t=false; 
            ans++;//记录答案个数 
            key[++cnt]=i;//记录每个解的值 
        }
    }
    if(t){
        cout<<ans<<endl;//如果t未改变则说明解的个数为0 
        return 0;
    }
    print(ans);
    printf("\n");
    for(ll i=1;i<=cnt;i++){
        print(key[i]);
        printf("\n");
    }
    return 0;
}

然后呢算法时间复杂度大概是O(n*m),这样子这道题就A掉了

发布了41 篇原创文章 · 获赞 58 · 访问量 6万+

猜你喜欢

转载自blog.csdn.net/a1351937368/article/details/78087687
今日推荐