[题解]NOIP2014

\(\bf D1\)

\(\bf T3\) 飞扬的小鸟

看到题目毫无头绪QwQ,后来划到SkyWT的博客(SkyWT最偷学!!!)发现可以DP

最naive的想法就是枚举在每一个位置向上跳了多少次然后转移,但是这样复杂度太大了。于是我们发现一下,这好像和完全背包差不多,那么就可以类似完全背包转移

代码

细节比较多,代码还是放一下吧

F了好多回,论对拍的重要性

void SOLVE(){
    rep(i,0,n)rep(j,0,m)f[i][j]=INF;
    rep(i,0,m)f[0][i]=0;
    rep(i,0,n-1){
        rep(j,1,m){
            int pos=min(m,j+a[i].x);
            if(j>a[i].l&&j<a[i].r)f[i+1][pos]=min(f[i+1][pos],f[i][j]+1);
            f[i+1][pos]=min(f[i+1][pos],f[i+1][j]+1);//可能j不合法,但是pos合法
        } //跳和不跳要分开,否则可能出现某一个位置既向下又向上的
        rep(j,a[i].y+1,m){
            if(j<=a[i].l||j>=a[i].r)continue;
            int pos=j-a[i].y;
            if(pos<=a[i+1].l||pos>=a[i+1].r)continue;
            f[i+1][pos]=min(f[i+1][pos],f[i][j]);
        }
        rep(j,1,m){
            if(j>a[i].l&&j<a[i].r)f[i][0]=min(f[i][0],f[i][j]);
        }
    }
    rep(i,1,m){
        if(i>a[n].l&&i<a[n].r)f[n][0]=min(f[n][0],f[n][i]);
    }
    rep(i,1,n){
        if(f[i][0]==INF){
            printf("0\n%d\n",cnt[i-1]);
            return;
        }
    }
    printf("1\n%d\n",f[n][0]);
    return;
}

\(\bf D2\)

T3 解方程

题目描述

分析

首先考虑对于一个\(x\),怎么在\(O(n)\)时间内求出上面的式子的答案:

原式\(f(x)=a_0+x(a_1+x(a_2+x(.....+xa_n)))\)

但是数据范围实在是太大了,考虑哈希:

对于质数\(P\),如果\(f(x)\)%\(P=0\),那么\(f(x)\)可能就是0,为了减小犯错的几率,可以多取几个质数

并且,我们发现\(f(x)\equiv f(x+P*i)(mod P)\),所以我们需要枚举\(P\)以内的数就可以了

代码

#include<bits/stdc++.h>
#define rep(X,A,B) for(int X=A;X<=B;X++)
#define tep(X,A,B) for(int X=A;X>=B;X--)
#define LL long long
const int M=1000010;
const int N=110;
const int MX=5;
using namespace std;

int n,m;
int MOD[MX];
int a[N][MX];
int chk[M],ans[M];

int add(int x,int y,int z){return x+y>=MOD[z]?x+y-MOD[z]:x+y;}
int dec(int x,int y,int z){return x>=y?x-y:x+MOD[z]-y;}

void read(int id){
    char c=getchar();
    bool flg=0;
    for(;c<'0'||c>'9';c=getchar())flg|=(c=='-');
    for(;c>='0'&&c<='9';c=getchar()){
        rep(i,0,3)a[id][i]=add(a[id][i]*10%MOD[i],(c^48),i);
    }
    if(flg)a[id][4]=-1;else a[id][4]=1;
}

void READ(){
    MOD[0]=2333;MOD[1]=23333;MOD[2]=24547;MOD[3]=4111;
    scanf("%d%d",&n,&m);
    rep(i,0,n)read(i);
}

int CHK(int x,int z){
    int now=0;
    tep(i,n,0){
        if(a[i][4]==1)now=add(now*x%MOD[z],a[i][z],z);
        else now=dec(now*x%MOD[z],a[i][z],z);
    }
    return (now==0);
}

void SOLVE(){
    rep(o,0,3){
        rep(i,1,MOD[o]-1){
            if(i>m)break;
            if(CHK(i,o)){
                for(int now=i;now<=m;now+=MOD[o])chk[now]++;
            }
        }
    }
    int cnt=0;
    rep(i,1,m)if(chk[i]==4)ans[++cnt]=i;
    printf("%d\n",cnt);
    rep(i,1,cnt)printf("%d\n",ans[i]);
}

int main(){
    READ();
    SOLVE();
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/SCL123/p/11839528.html