zoukankan      html  css  js  c++  java
  • 6.29集训--集训模拟赛3

    总结

    今天集齐了四种颜色



    这一次真是水翻了,除去第一题送分题,后三道题只拿了50分
    开考后完全不在状态,最后的一个半小时一点代码都没有写出来

    A、李时珍的皮肤衣




    分析

    (n)的数据最大达到了(10^{10}),显然是一道结论题
    枚举几组样例可以发现,最终的答案为(2^{n-1}+1)(n)取模
    其实就是相当于二进制下的进位
    因为(n)很大,所以要用快速幂

    代码

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    ll n;
    ll ksm(ll now,ll fa){
        ll xz=now;
        ll ans=1;
        while(fa){
            if(fa&1){
                ans*=xz;
                ans=ans%n;
            }
            fa=(fa>>1);
            xz=xz*xz%n;
        }
        return ans%n;
    }
    int main(){
        scanf("%lld",&n);
        printf("%lld
    ",(ksm(2,n-1)+1)%n);
        return 0;
    }
    

    B、马大嘴的废话




    分析

    如果直接暴力枚举的话可以得到60分
    然而暴力写挂了
    这道题的最优解要用到AC自动机,但是AC自动机并没有学
    林大佬用哈希表过了这道题,但模数比较难取,而且不用c++11会T
    其实这一道题可以用Tire树维护

    60代码

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn=20005;
    char s[maxn][25];
    int main(){
        int n;
        scanf("%d",&n);
        for(int i=1;i<=n;i++){
            scanf("%s",s[i]);
        }
        int m;
        scanf("%d",&m);
        for(int i=1;i<=m;i++){
            char a[25];
            scanf("%s",a);
            int ans=0;
            int now=strlen(a);
            int be=0;
            for(int j=1;j<=n;j++){
               if(strstr(s[j],a)!=NULL) ans++;
            }
            printf("%d
    ",ans);
        }
        return 0;
    }
    

    哈希表代码(林大佬)

    #include<cstdio>
    #include<algorithm>
    #include<unordered_map>
    #include<string>
    #include<cstring>
    #include<vector>
    using namespace std;
    
    #define ll long long
    
    const ll mod1=2e17+19260817;
    const int maxch=43;
    const int maxn=2e1+1;
    
    unordered_map<ll,int> mapp1;
    vector<ll> s1;
    unordered_map<ll,bool> vis1;
    char a[maxn];
    int n;
    
    void solve1(int l,int r)
    {
    	ll ans=0,now=1ll;
    	for(int i=l;i<=r;i++)
    	{
    		ans+=now*(a[i]-'a'+1)%mod1,ans%=mod1;
    		now*=(ll)maxch,now%=mod1;
    	}
    	if(vis1[ans]) return;
    	else vis1[ans]=1,s1.push_back(ans),mapp1[ans]++;
    }
    
    int calc1()
    {
    	ll ans=0,now=1ll;
    	for(int i=0;i<n;i++)
    	{
    		ans+=now*(a[i]-'a'+1)%mod1,ans%=mod1;
    		now*=(ll)maxch,now%=mod1;
    	}
    	return mapp1[ans];
    }
    
    int main()
    {
    	int m;
    	scanf("%d",&n);
    	while(n--)
    	{
    		scanf("%s",a);
    		m=strlen(a);
    		for(int i=0;i<m;i++)
    			for(int j=i;j<m;j++)
    				solve1(i,j);
    		for(int i=0;i<s1.size();i++) vis1[s1[i]]=0;
    		s1.clear();
    	}
    	scanf("%d",&m);
    	while(m--)
    	{
    		scanf("%s",a);
    		n=strlen(a);
    		printf("%d
    ",calc1());
    	}
    	return 0;
    }
    

    Tire树代码

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn=5e5+10;
    int tire[maxn][26],mark[maxn][26],cnt[maxn][26];
    int n,m;
    int tot=0;
    char s[30];
    char a[30];
    void insert(int l,int r,int id){
    	int now=0;
    	int t;
    	for(int i=l;i<=r;i++){
    		t=s[i]-'a';
    		if(tire[now][t]){
    			if(id!=mark[now][t]){
    			    cnt[now][t]++;
    			    mark[now][t]=id;
    			}
    		}
    		else {
    			tire[now][t]=++tot;
    			mark[now][t]=id;
    			cnt[now][t]=1;
    		}
    		now=tire[now][t];
    	}
    }
    int query(char a[]){
    	int len=strlen(a);
    	int now=0,ans=0;
    	for(int i=0;i<len;i++){
    		int t=a[i]-'a';
    		if(tire[now][t]==0)return 0;
    		ans=cnt[now][t];
    		now=tire[now][t];
    	}
    	return ans;
    }
    int main(){
    	cin>>n;
    	for(int i=1;i<=n;i++){
    		cin>>s;
    		int len=strlen(s);
    		for(int j=0;j<len;j++){
    			insert(j,len-1,i);
    		}
    	}
    	cin>>m;
    	for(int i=1;i<=m;i++){
    		cin>>a;
    		cout<<query(a)<<'
    ';
    	}
    	return 0;
    }
    

    C、SSY的队列



    分析

    这道题的正解要用哈希表,所以先讲一下部分分的解法
    首先就是最简单的暴力枚举,求全排列,每次求出来之后判断是否合法,预计得分二十分
    还有一种七十分的状压DP解法
    我们设(f[i][j])为当前排好队的人的状态为(i),并且队伍末尾的人为(j)时的方案数
    所以有(f[i][j]+=f[i^(1<<(j-1))][k];)
    其中(abs(a[j]-a[k])%m!=0)
    (i&(1<<(j-1))!=0)
    (i&(1<<(k-1))!=0)

    20分暴力

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const ll mod=1234567891;
    const int maxn=35;
    ll a[maxn];
    int main(){
        int n;
        scanf("%d",&n);
        for(int i=1;i<=n;i++){
            scanf("%lld",&a[i]);
        }
        ll m;
        scanf("%lld",&m);
        sort(a+1,a+1+n);
        ll ans=0;
        while(1){
            bool jud=0;
            for(int i=1;i<n;i++){
                if(abs(a[i]-a[i+1])%m==0){
                    jud=1;
                    break;
                }
            }
            if(jud==0) ans++;
            if(next_permutation(a+1,a+n+1)==0) break;
        }
        printf("%lld
    ",ans%mod);
        return 0;
    }
    

    70分状压

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int maxn=23;
    const ll mod=1234567891;
    ll f[1<<maxn][maxn],a[maxn];
    int main(){
        int n;
        scanf("%d",&n);
        for(int i=1;i<=n;i++){
            scanf("%lld",&a[i]);
            f[1<<(i-1)][i]=1;
        }
        ll m;
        scanf("%lld",&m);
        int mmax=(1<<n)-1;
        for(int i=0;i<=mmax;i++){
            for(int j=1;j<=n;j++){
                for(int k=1;k<=n;k++){
                    if(abs(a[j]-a[k])%m==0 || (i&(1<<(j-1))==0) || (i&(1<<(k-1))==0)) continue;
                    f[i][j]+=f[i^(1<<(j-1))][k];
                    f[i][j]%=mod;
                }
            }
        }
        ll ans=0;
        for(int i=1;i<=n;i++){
            ans+=f[mmax][i];
            ans%=mod;
        }
        printf("%lld
    ",ans);
        return 0;
    }
    

    D、清理牛棚



    分析

    这道题的解法很多,有线性DP、线段树优化DP、单调栈优化DP、最短路

    最短路解法

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int maxn=2e6+5;
    struct asd{
        int from,to,next;
        ll val;
    }b[maxn];
    int head[maxn],tot=1;
    void ad(int aa,int bb,ll cc){
        b[tot].from=aa;
        b[tot].to=bb;
        b[tot].val=cc;
        b[tot].next=head[aa];
        head[aa]=tot++;
    }
    struct jie{
        int num;
        ll jl;
        jie(int aa=0,ll bb=0){
            num=aa,jl=bb;
        }
        bool operator < (const jie& A) const{
            return jl>A.jl;
        }
    };
    ll dis[maxn];
    bool vis[maxn];
    priority_queue<jie> q;
    void dij(int xx){
        memset(dis,0x3f,sizeof(dis));
        dis[xx]=0;
        q.push(jie(xx,0));
        while(!q.empty()){
            int now=q.top().num;
            q.pop();
            if(vis[now]) continue;
            vis[now]=1;
            for(int i=head[now];i!=-1;i=b[i].next){
                int u=b[i].to;
                if(dis[u]>dis[now]+b[i].val){
                    dis[u]=dis[now]+b[i].val;
                    q.push(jie(u,dis[u]));
                }
            }
        }
    }
    int main(){
        memset(head,-1,sizeof(head));
        int n,m,e;
        scanf("%d%d%d",&n,&m,&e);
        for(int i=1;i<=n;i++){
            int aa,bb;
            ll cc;
            scanf("%d%d%lld",&aa,&bb,&cc);
            ad(aa,bb+1,cc);
        }
        for(int i=m;i<e;i++){
            ad(i+1,i,0);
        }
        dij(m);
        if(dis[e+1]==0x3f3f3f3f3f3f3f3f){
            printf("-1
    ");
            return 0;
        }
        printf("%lld
    ",dis[e+1]);
        return 0;
    }
    
    

    线性DP解法

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int maxn=100005;
    ll f[maxn];
    struct asd{
        int l,r;
        ll hd;
    }b[maxn];
    bool cmp(asd aa,asd bb){
        if(aa.r==bb.r) return aa.l<bb.l;
        return aa.r<bb.r;
    }
    int main(){
        memset(f,0x3f,sizeof(f));
        int n,m,e;
        scanf("%d%d%d",&n,&m,&e);
        for(int i=1;i<=n;i++){
            scanf("%d%d%lld",&b[i].l,&b[i].r,&b[i].hd);
        }
        sort(b+1,b+1+n,cmp);
        f[m]=0;
        ll ans=0x3f3f3f3f3f3f3f3f;
        for(int i=1;i<=n;i++){
            for(int j=b[i].l-1;j<b[i].r;j++){
                f[b[i].r]=min(f[b[i].r],f[j]+b[i].hd);
            }
            if(b[i].l<=e && b[i].r>=e) ans=min(ans,f[b[i].r]);
        }
        if(ans==0x3f3f3f3f3f3f3f3f) printf("-1
    ");
        else printf("%d
    ",ans);
        return 0;
    }
    
    

    线段树优化DP

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    
    #define ll long long
    
    const int maxe=9e4+1;
    const int maxn=1e4+1;
    const ll inf=0x3f3f3f3f3f3f3f3f;
    
    struct Node
    {
    	int x,y,val;
    }a[maxn];
    ll mn[maxe<<2];
    
    void dfs(int x,int l,int r,int pos,ll val)
    {
    	if(l==r)
    	{
    		mn[x]=min(mn[x],val);
    		return;
    	}
    	int mid=l+r>>1;
    	if(pos<=mid) dfs(x<<1,l,mid,pos,val);
    	else dfs(x<<1|1,mid+1,r,pos,val);
    	mn[x]=min(mn[x<<1],mn[x<<1|1]);
    }
    
    ll query(int x,int l,int r,int left,int right)
    {
    	if(l>=left&&r<=right) return mn[x];
    	int mid=l+r>>1;
    	ll ans=inf;
    	if(left<=mid) ans=min(ans,query(x<<1,l,mid,left,right));
    	if(right>mid) ans=min(ans,query(x<<1|1,mid+1,r,left,right));
    	return ans;
    }
    
    int cmp(const Node &x,const Node &y)
    {
    	return x.y<y.y;
    }
    
    int main()
    {
    	int n,m,e;
    	scanf("%d%d%d",&n,&m,&e);
    	m-=2;e-=m;
    	memset(mn,0x3f,sizeof(mn));
    	for(int i=0;i<n;i++) scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].val),a[i].x-=m,a[i].y-=m;
    	dfs(1,1,e,1,0);
    	sort(a,a+n,cmp);
    	for(int i=0;i<n;i++)
    	{
    		ll now=query(1,1,e,a[i].x-1,a[i].y-1);
    		if(now!=inf) dfs(1,1,e,a[i].y,now+(ll)a[i].val);
    	}
    	ll ans=query(1,1,e,e,e);
    	printf("%lld",ans==inf?-1:ans);
    	return 0;
    }
    
  • 相关阅读:
    day13 python学习 迭代器,生成器
    day12 python学习 装饰器
    day10 python学习 函数的嵌套命名空间作用域 三元运算 位置参数 默认参数 动态参数
    day11 python学习 函数的建立,返回值,参数
    day7 python学习
    2易错概念和点
    day8 python学习 集合 深浅拷贝
    1.易错概念和点
    python_基础算法
    css基础示例代码
  • 原文地址:https://www.cnblogs.com/liuchanglc/p/13208804.html
Copyright © 2011-2022 走看看