[题解]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;
}
posted @ 2019-11-12 07:58  硫氯  阅读(93)  评论(0编辑  收藏  举报