レポートを解決NOIP2014解決方程式

羅バレー(原題参照https://www.luogu.org/problem/show?pid=2312が
QWQは
この事が作られた操作の数を減らすために使用することができ、多項式の値を計算する方法です-ホーナー法と呼ばれるものを持っているようだがホーナー法それのBaiduの百科事典を説明するために-それをTATリンクを知っている必要がありますが、これは、高校数学内容であることは、基本的には高校に行ってきました:( https://baike.baidu.com/item/ホーナー法/ 449196、FR =?アラジン)
この質問は〜私たちはああライン上でカウントするホーナー法により、多項式として左にそれを行うことができますです

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から1によって、次の1です〜メートル列挙値式は、限り、式の値が良い上の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を防ぐために、大きな素数であり、最適化を読んで覚えることができる
機能が読み出され、高速なリードインとアウトプットの高速友人〜何その後、
BOOLトントンが解けるかどうかを決定するために使用されます。ソリューションは、レコード数にCNT。和多項式の結果を記録するために、我々はそうでない場合は10ポイントには、キー値の配列多項式係数は、の溶液のそれぞれの値を記録するために使用され、配列Aが記録されている、その合計がqjs機能をクリアする必要があります覚えておく必要があります
コピーを注釈付きのソリューション:

#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 ビュー60000 +

おすすめ

転載: blog.csdn.net/a1351937368/article/details/78087687
おすすめ