[题解]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;
}