NOIP 2017 Day1 题解?

来源:互联网 发布:js中get和post的区别 编辑:程序博客网 时间:2024/05/17 02:43

NOIP 2017 Day1 我的程序(AC)

题目详解

T1

#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#include<cstdlib>#include<vector>#include<queue>#include<cmath>#define LL long longusing namespace std ;int main(){    freopen("math.in","r",stdin);    freopen("math.out","w",stdout);    LL a,b;    scanf("%lld%lld",&a,&b);    if (!(a&1)) swap(a,b);    LL tmp1=a-1;    LL tmp2=a-2;    LL tmp3=(a-2)+(a-1)*(b-2);    printf("%lld\n",tmp3);    return 0;}

  上面的tmp3我是用找规律(数列)弄出来的,考试的时候脑子抽了,居然没化简,但是对拍了没错我也不虚,就这样交了。
   其实就是积减和公式A×BAB就是答案。


T2

#include<iostream>#include<cstdio>#include<cstring>#include<cstdlib>#include<algorithm>#include<queue>#include<vector>using namespace std ;const int N=2333;const int M=27;int val[N],used[M];int T,goal=0,noin=0,top=1,n,ans,nowans; bool ERR=0;string st;void init(){    cin>>n;    cin>>st;//cerr<<n<<' '<<st<<' ';    int len=st.size();    if (st[2]=='n')         for(int i=4;i<=len-1;i++)            if (st[i]>='0'&&st[i]<='9') goal=goal*10+st[i]-'0';                else break;//cerr<<"goal="<<goal<<endl;}void F(){    char x;    string y,z;    cin>>x>>y>>z;//cerr<<x<<' '<<y<<' '<<z<<endl;    int id=x-'a',u=0,v=0;    int lenu=y.size(),lenv=z.size();    if (used[id]||ERR)     {        ERR=1;//cerr<<"ERR?"<<endl;        return ;    }    used[id]=top;//cerr<<"id="<<id<<endl;    if (y=="n") u=2333;        else for (int i=0;i<=lenu-1;i++) u=u*10+y[i]-'0';    if (z=="n") v=2333;        else for (int i=0;i<=lenv-1;i++) v=v*10+z[i]-'0';//cerr<<u<<' '<<v<<endl;    if (u>v||noin) noin++,val[top]=0;        else if (v-u>=1000) val[top]=1;            else val[top]=0;    nowans+=val[top];    ans=max(ans,nowans);            top++;}void E(){    top--;    if (top<1||ERR)    {        ERR=1;        return ;    }    for (int i=0;i<=26;i++)        if (used[i]==top)             used[i]=0;    if (noin) noin--;    nowans-=val[top];    ans=max(ans,nowans);}bool check(){//cerr<<"ans="<<ans<<endl;    if (ans!=goal) return 0;    return 1;}void reset(){    goal=ERR=ans=nowans=noin=0;    top=1;    memset(used,0,sizeof used);    memset(val,0,sizeof val);}void solve(){    for(int i=1;i<=n;i++)    {        cin>>st;//cerr<<st<<endl;        if (st=="F") F();            else if (st=="E") E();    }    if (ERR||top!=1) printf("ERR\n");        else if (check()) printf("Yes\n");            else printf("No\n");}int main(){//  freopen("1.in","r",stdin);    cin>>T;    while (T--)    {        reset();        init();        solve();    }    return 0;}

   这题是纯模拟题,但是为了提高准确率,我比较推荐用模块化的写法。用栈维护循环自然不用说,需要注意的就是每次都要清空。因为题目说了N是个远大于100的数,其实可以把N转化成具体数字,统一操作的话似乎容易做很多,可以更清晰思路,模块化的好处就体现在这里了。


T3

#include<iostream>#include<cstdio>#include<cstring>#include<cstdlib>#include<algorithm>#include<queue>#include<vector>using namespace std ;const int N=100100;const int M=200200;const int K=55;bool flag=0;int cnt,n,m,k,mod,ans,T;int f[N][K],go[N][K],vis[N],head[N],dis[N];queue<int>q;struct edge{    int v,w,nxt;}e[M];void add(int u,int v,int w){    cnt++;    e[cnt].v=v;    e[cnt].w=w;    e[cnt].nxt=head[u];    head[u]=cnt;}void init(){    scanf("%d%d%d%d",&n,&m,&k,&mod);    for (int i=1;i<=m;i++)    {        int u,v,w;        scanf("%d%d%d",&u,&v,&w);        add(v,u,w);    }}void spfa(int s,int t){    dis[s]=0;    vis[s]=1;    q.push(s);    while (!q.empty())    {        int u=q.front(); q.pop();        for (int i=head[u];i;i=e[i].nxt)        {            int v=e[i].v,w=e[i].w;            if (dis[u]+w<dis[v]||dis[v]==-1)            {                dis[v]=dis[u]+w;                if (!vis[v])                {                    vis[v]=1;                    q.push(v);                }            }        }        vis[u]=0;    }}int dfs(int u,int k){    if (go[u][k])    {        flag=1;        return 0;    }    if (f[u][k]!=-1) return f[u][k];    go[u][k]=1;    int re=0;    for (int i=head[u];i;i=e[i].nxt)    {        int v=e[i].v,w=e[i].w,tmp;        tmp=k-(dis[u]+w-dis[v]);        if (tmp<0||tmp>k) continue ;        re=(re+dfs(v,tmp))%mod;        if (flag)         {            go[u][k]=0;            return 0;        }    }    go[u][k]=0;    if (u==1&&k==0) re++;    return f[u][k]=re;}void solve(){    spfa(n,1);    for (int i=0;i<=k;i++)    {//      memset(go,0,sizeof go);        ans=(ans+dfs(n,i))%mod;    }    if (flag) printf("-1\n");        else printf("%d\n",ans);}void reset(){    ans=flag=0;    cnt=0;    while (!q.empty()) q.pop();    memset(dis,-1,sizeof dis);    memset(f,-1,sizeof f);    memset(vis,0,sizeof vis);    memset(head,0,sizeof head);    memset(go,0,sizeof go);}int main(){//  freopen("1.in","r",stdin);//  freopen("1.out","w",stdout);    scanf("%d",&T);    while (T--)    {        reset();        init();        solve();    }    return 0;}

  这题我一开始打得很快,因为是搜索,比较熟练,但是码完后交上去RE了一个点。这个RE的点我查了很久,为什么会RE。但是我发现我的程序里的错误是 用了NK^2的时间。因为 for (k) memset(nk) ,但是显示的是RE错误。所以,memset应该是调用空间的,RE了可能是因为memset炸空间。

阅读全文
0 0