20160728noip模拟赛zld

前言:单独对题面描述的评分->QQ图片20160719153247

imageimage
【题解】把相邻长度为2的子串两两连边,跑欧拉路

/*明天再写,先贴一份方老师代码压压惊*/

#include<map>
#include<stack>
#include<queue>
#include<cstdio>
#include<string>
#include<vector>
#include<cstring>
#include<complex>
#include<iostream>
#include<assert.h>
#include<algorithm>
using namespace std;
#define inf 1001001001
#define infll 1001001001001001001LL
#define FOR0(i,n) for(int (i)=0;(i)<(n);++(i))
#define FOR1(i,n) for(int (i)=1;(i)<=(n);++(i))
#define ll long long
#define dbg(vari) cerr<<#vari<<" = "<<(vari)<<endl
#define gmax(a,b) (a)=max((a),(b))
#define gmin(a,b) (a)=min((a),(b))
#define ios0 ios_base::sync_with_stdio(0)
#define Ri register int
#define gc getchar()
#define il inline
il int read(){
    bool f=true;
    Ri x=0;char ch;
    while(!isdigit(ch=gc))if(ch=='-')f=false;
    while(isdigit(ch)){x=(x<<1)+(x<<3)+ch-'0';ch=gc;}
    return f?x:-x;
}
#define gi read()
#define FO(x) freopen(#x".in","r",stdin),freopen(#x".out","w",stdout);
int hash(char a,char b){
    return (int)a*333+b; 
}
char A,B; 
void rhash(int a){
    B=a%333;
    A=(a-B)/333; 
}
struct edge{
    int to,next;
}e[666666];
int cnt,last[666666],dgr[666666];
void insert(int a,int b){
    e[++cnt]=(edge){b,last[a]};last[a]=cnt;++dgr[a];++dgr[b];
}
int T,mark[666666],ans[666666],_ans=0;
void dfs(int v){
    rhash(v);
    ans[++_ans]=v;
    for(int i=last[v];i;i=e[i].next){
        if(!mark[i]){
            mark[i]=true;
            dfs(e[i].to);
        }
    }
}
int main(){
    FO(recover);
    T=gi;
    while(T--){
        int n=gi;_ans=0;
        memset(last,0,sizeof(last));
        memset(dgr,0,sizeof(dgr));
        cnt=0;int source=0;
        FOR1(i,n){
            char str[6];
            scanf("%s",str+1);
            if(!source)source=hash(str[1],str[2]);
            insert(hash(str[1],str[2]),hash(str[2],str[3]));
        }
        int oddcnt=0;
        FOR1(i,hash('z','z')){
            oddcnt+=dgr[i]&1;
        }
        if(oddcnt>2||oddcnt==1)puts("NO");
        else{
            if(oddcnt){
                FOR1(i,hash('z','z')){
                    if(dgr[i]&1){
                        dfs(i);break;
                    }
                }
            }else{
                dfs(source);
            }
        }
        FOR1(i,_ans){
            rhash(ans[i]);
            if(i==1){putchar(A),putchar(B);}
            else{putchar(B);} 
        }
        puts("");
    }
}
image

image

【题解】

题意相当于是给定相邻两两的大小关系,求方案数

那么可以得到一个dp方程dp[i][j] 表示1-i的排列数为j的方案数

那么

a_{i-1}<a_idp[i][j]=\sum_{k=1}^{j-1}dp[i-1][k]

否则dp[i][j]=\sum_{k=j}^{i-1}dp[i-1][k]

这样看起来是n^3的,很显然可以应用前缀和优化到n^2

#include<map>
#include<stack>
#include<queue>
#include<cstdio>
#include<string>
#include<vector>
#include<cstring>
#include<complex>
#include<iostream>
#include<assert.h>
#include<algorithm>
using namespace std;
#define pb push_back
#define inf 1001001001
#define infll 1001001001001001001LL
#define FOR0(i,n) for(int (i)=0;(i)<(n);++(i))
#define FOR1(i,n) for(int (i)=1;(i)<=(n);++(i))
#define mp make_pair
#define pii pair<int,int>
#define ll long long
#define ld double
#define vi vector<int>
#define SZ(x) ((int)((x).size()))
#define fi first
#define se second
#define RI(n) int (n); scanf("%d",&(n));
#define RI2(n,m) int (n),(m); scanf("%d %d",&(n),&(m));
#define RI3(n,m,k) int (n),(m),(k); scanf("%d %d %d",&(n),&(m),&(k));
template<typename T,typename TT> ostream& operator<<(ostream &s,pair<T,TT> t) {return s<<"("<<t.first<<","<<t.second<<")";}
template<typename T> ostream& operator<<(ostream &s,vector<T> t){FOR0(i,sz(t))s<<t[i]<<" ";return s; }
#define dbg(vari) cerr<<#vari<<" = "<<(vari)<<endl
#define all(t) t.begin(),t.end()
#define FEACH(i,t) for (typeof(t.begin()) i=t.begin(); i!=t.end(); i++)
#define TESTS RI(testow)while(testow--)
#define FORZ(i,a,b) for(int (i)=(a);(i)<=(b);++i)
#define FORD(i,a,b) for(int (i)=(a); (i)>=(b);--i)
#define gmax(a,b) (a)=max((a),(b))
#define gmin(a,b) (a)=min((a),(b))
#define ios0 ios_base::sync_with_stdio(0)
using namespace std;
#define Ri register int
#define gc getchar()
#define il inline
il int read(){
    bool f=true;
    Ri x=0;char ch;
    while(!isdigit(ch=gc))if(ch=='-')f=false;
    while(isdigit(ch)){x=(x<<1)+(x<<3)+ch-'0';ch=gc;}
    return f?x:-x;
}
#define gi read()
#define FO(x) freopen(#x".in","r",stdin),freopen(#x".out","w",stdout);
int a[2333],s[2333];
int b[2333],ans,f[2333][2333]={{0,1}};
int main(){
    FO(good);    
    TESTS{
        RI2(n,m);
        memset(b,0,sizeof(b));
        FOR1(i,m)s[i]=gi,b[s[i]]=true;
        FOR1(i,n-1){
            int t=0;
            if(b[i]) 
            FOR1(k,i+1){
                f[i][k]=t;
                t=(t+f[i-1][k])%1000000007;
            }else
            FORD(k,i+1,1){
                t=(t+f[i-1][k])%1000000007;
                f[i][k]=t;
            }
        }
        int ans=0;
        FOR1(i,n)ans=(ans+f[n-1][i])%1000000007;
        cout<<ans<<endl; 
    }
    return 0; 
}

T3

题面

输入n,s

当s=1时,是http://codeforces.com/contest/690/problem/A1

当s=0时,是http://codeforces.com/contest/690/problem/A2

【题解】

首先s=1的情况比较好做,答案就是\frac{n+1}{2}

当s=0时,我们可以发现,当n=2^s时,ZY一个钻石都不要出,就能活命

那么当n=2^s+2k对于多出来的2k人,可以沿用s=1的策略

如果n是一个奇数,更加简单啊,答案是\frac{n-1}{2}

#include<map>
#include<stack>
#include<queue>
#include<cstdio>
#include<string>
#include<vector>
#include<cstring>
#include<complex>
#include<iostream>
#include<assert.h>
#include<algorithm>
using namespace std;
#define pb push_back
#define inf 1001001001
#define infll 1001001001001001001LL
#define FOR0(i,n) for(int (i)=0;(i)<(n);++(i))
#define FOR1(i,n) for(int (i)=1;(i)<=(n);++(i))
#define mp make_pair
#define pii pair<int,int>
#define ll long long
#define ld double
#define vi vector<int>
#define SZ(x) ((int)((x).size()))
#define fi first
#define se second
#define RI(n) int (n); scanf("%d",&(n));
#define RI2(n,m) int (n),(m); scanf("%d %d",&(n),&(m));
#define RI3(n,m,k) int (n),(m),(k); scanf("%d %d %d",&(n),&(m),&(k));
template<typename T,typename TT> ostream& operator<<(ostream &s,pair<T,TT> t) {return s<<"("<<t.first<<","<<t.second<<")";}
template<typename T> ostream& operator<<(ostream &s,vector<T> t){FOR0(i,sz(t))s<<t[i]<<" ";return s; }
#define dbg(vari) cerr<<#vari<<" = "<<(vari)<<endl
#define all(t) t.begin(),t.end()
#define FEACH(i,t) for (typeof(t.begin()) i=t.begin(); i!=t.end(); i++)
#define TESTS RI(testow)while(testow--)
#define FORZ(i,a,b) for(int (i)=(a);(i)<=(b);++i)
#define FORD(i,a,b) for(int (i)=(a); (i)>=(b);--i)
#define gmax(a,b) (a)=max((a),(b))
#define gmin(a,b) (a)=min((a),(b))
#define ios0 ios_base::sync_with_stdio(0)
using namespace std;
#define Ri register int
#define gc getchar()
#define il inline
il int read(){
    bool f=true;
    Ri x=0;char ch;
    while(!isdigit(ch=gc))if(ch=='-')f=false;
    while(isdigit(ch)){x=(x<<1)+(x<<3)+ch-'0';ch=gc;}
    return f?x:-x;
}
#define gi read()
#define FO(x) freopen(#x".in","r",stdin),freopen(#x".out","w",stdout);
int main() {
    FO(distribute);
    TESTS{
        int n,s;
        n=gi;s=gi;
        if(s==1)printf("%d\n",(n+1)/2);
        else{
            if(n&1){
                printf("%d\n",n/2);
                continue;
            }
            n/=2;
            int d=0;
            while((1<<d)<=n)
                ++d;
            --d;
            n-=(1<<d);
            printf("%d\n",n);
        }
    }
    return 0;
}
posted @ 2016-08-01 16:09  zhouyis  阅读(287)  评论(0编辑  收藏  举报