• hgoi#20191106


    T1-旅行家

    给你 $ n $ 种能前进 $ A_i $ 步的装置,每种有 $ B_i $ 个
    终点是用完装置到达的地方,现在限制了一些点,问你到达终点的方案数

    解法

    数据范围很小,直接状压dp

    ac代码

    #pragma GCC optimize(2)
    #include<bits/stdc++.h>
    #define ll long long
    #define mod 100000007
    using namespace std;
    namespace fast_IO
    {
        const int IN_LEN = 10000000, OUT_LEN = 10000000;
        char ibuf[IN_LEN], obuf[OUT_LEN], *ih = ibuf + IN_LEN, *oh = obuf, *lastin = ibuf + IN_LEN, *lastout = obuf + OUT_LEN - 1;
        inline char getchar_(){return (ih == lastin) && (lastin = (ih = ibuf) + fread(ibuf, 1, IN_LEN, stdin), ih == lastin) ? EOF : *ih++;}
        inline void putchar_(const char x){if(oh == lastout) fwrite(obuf, 1, oh - obuf, stdout), oh = obuf; *oh ++= x;}
        inline void flush(){fwrite(obuf, 1, oh - obuf, stdout);}
        template<typename T>void read(T &x)
    	{
    		x=0;char c=getchar_();
    		for(;!isdigit(c);c=getchar_());
    		for(;isdigit(c);c=getchar_())x=x*10+c-'0';
    	}
        inline void write(ll x)
    	{
            if(x>9)write(x/10);
            putchar_(x%10+'0');
        }
        inline void writeln(ll x)
        {
    		write(x),putchar_('
    ');
    	}
    };
    using namespace fast_IO;
    unordered_map<long long,bool>lm;
    int n,m,a[10],b[10],p[10],ct[10],dp[5000000];
    ll x;
    ll calc()
    {
    	ll ans=0;
    	for(int i=1;i<=n;i++)
    		ans+=1ll*a[i]*ct[i];
    	return ans;
    }
    int main()
    {
    	freopen("traveller.in","r",stdin);
    	freopen("traveller.out","w",stdout);
    	read(n),p[0]=1;
    	for(int i=1;i<=n;i++)
    		read(a[i]),read(b[i]),
    		p[i]=p[i-1]*(b[i]+1);
    	read(m);
    	for(int i=1;i<=m;i++)
    		read(x),lm[x]=1;
    	dp[0]=1;
    	for(int i=0;i<p[n]-1;i++)
    	{
    		for(int j=1;j<=n;j++)ct[j]=i%p[j]/p[j-1];
    		if(!lm.count(calc()))for(int j=1;j<=n;j++)
    			(ct[j]<b[j])&&((dp[i+p[j-1]]+=dp[i])%=mod);
    	}
    	writeln(dp[p[n]-1]),flush();
    	return 0;
    }
    

    T2-序列

    给你 $ n $ 个区间,每次询问 $ 1-i $ 区间中满足 $ f(x oplus y) equiv 1 pmod{2} $ 的无序数对 $ (x,y) ( ) f(x) $ 表示 $ x $ 的二进制分解中 $ 1 $ 的个数

    解法

    易得满足题意的数对 $ (x,y) $ 一定有 $ f(x) mod 2 ot= f(y) mod 2 $
    所以我们统计区间里 $ f(x) $ 为奇数和偶数的个数
    对于一个连续的区间,设 $ g(x) $ 表示 $ 1-x $ 中 $ f(x) $ 为奇数的个数
    这怎么求呢,我们发现 $ 0,1,2,3,4,5... $ 每两个数有一个数的 $ f(x) $ 为奇数
    我们只要检验多出来的一个数即可
    对于不连续的区间,每次我们塞进去一个区间,用vector暴力合并即可

    ac代码

    #pragma GCC optimize(2)
    #include<bits/stdc++.h>
    #define fir first
    #define sec second
    #define mp make_pair
    #define int long long 
    using namespace std;
    struct node
    {
    	int l,r,a,b;
    	bool operator<(const node&x)const{return l<x.l;}
    }tmp;
    vector<node>p;
    int n,l,r,a,b;
    pair<int,int>operator+(pair<int,int>a,pair<int,int>b)
    {
    	return mp(a.fir+b.fir,a.sec+b.sec);
    }
    pair<int,int>operator-(pair<int,int>a,pair<int,int>b)
    {
    	return mp(a.fir-b.fir,a.sec-b.sec);
    }
    pair<int,int>f(pair<int,int>x)
    {return mp(x.sec,x.fir);}
    pair<int,int>spe(int x)
    {
    	int cnt=0;
    	while(x)
    		cnt+=x&1,x/=2;
    	if(cnt&1)return mp(1,0);
    	else return mp(0,1);
    }
    pair<int,int>calc(int x)
    {
    	if(x&1)return mp(x/2+1,x/2);
    	else return mp(x/2+1,x/2)-spe(x+1);
    }
    void ins(int l,int r)
    {
    	tmp={l,r,0,0};
    	int pos=lower_bound(p.begin(),p.end(),tmp)-p.begin();
    	if(pos!=0&&p[pos-1].r>=tmp.l-1)
    	{
    		pos--;
    		tmp.l=p[pos].l;
    		if(p[pos].r>tmp.r)tmp.r=p[pos].r;
    		a-=p[pos].a,b-=p[pos].b;
    		p.erase(p.begin()+pos);
    	}
    	for(int i=pos;i<p.size();i++)
    	{
    		if(p[i].l>tmp.r+1)break;
    		tmp.r=max(tmp.r,p[i].r);
    		a-=p[i].a,b-=p[i].b;
    		p.erase(p.begin()+i),i--;
    	}
    	pair<int,int>pp=calc(tmp.r)-calc(tmp.l-1);
    	tmp.a=pp.fir,tmp.b=pp.sec;
    	a+=tmp.a,b+=tmp.b;
    	p.insert(p.begin()+pos,tmp);
    }
    signed main()
    {
    //	freopen("sequence.in","r",stdin);
    //	freopen("sequence.out","w",stdout);
    	scanf("%lld",&n);
    	for(int i=1;i<=n;i++)
    		scanf("%lld%lld",&l,&r),ins(l,r),printf("%lld
    ",1ll*a*b);
    	return 0;
    }
    

    T3-钢琴家

    给你一个字符串 $ S $ 和一些模式串 $ s[i] $
    改动一些字母使 $ S $ 成为 $ s[i] $ 的拼凑
    改动字母越少越好,按顺序输出改完之后 $ s[i] $ 的拼凑方案

    解法

    暴力dp, $ f[i] $ 表示考虑到第 $ i $ 位,都能匹配的最少改动
    再开一个数组记录方案就好了

    ac代码

    #pragma GCC optimize(2)
    #include<bits/stdc++.h>
    using namespace std;
    char a[1010],p[110][1010];
    int n,m,x,t,l[110],f[1010],ue[1010];
    inline int calc(int st,int s)
    {
    	int ans=0;
    	for(int i=1;i<=l[s];++i)
    		(a[st+i]!=p[s][i])&&(++ans);
    	return ans;
    }
    inline void print(int nw)
    {
    	if(nw==0)return;
    	print(nw-l[ue[nw]]);
    	printf("%s
    ",p[ue[nw]]+1);
    }
    int main()
    {
    	freopen("pianist.in","r",stdin);
    	freopen("pianist.out","w",stdout);
    	scanf("%s%d",a+1,&m),n=strlen(a+1);
    	for(int i=1;i<=m;++i)
    		scanf("%s",p[i]+1),l[i]=strlen(p[i]+1);
    	for(int i=1;i<=10;++i)scanf("%d",&x);
    	memset(f,0x3f,sizeof(f)),f[0]=0;
    	for(int i=0;i<n;++i)for(int j=1;j<=m;++j)if(i+l[j]<=n)
    		t=calc(i,j),(f[i]+t<f[i+l[j]])&&(f[i+l[j]]=f[i]+t,ue[i+l[j]]=j);
    	print(n);
    	return 0;
    }
    
  • 相关阅读:
    [Python+OpenCv]近似图像差异检测
    解决github登录不上
    aws 知识汇总
    ansible work 案例
    git命令
    Google Chrome浏览器离线安装包下载方式
    物理机U盘安装银河麒麟linux操作系统注意事项
    微信云函数的创建与配置
    CentOS6.5升级OpenSSH版本
    linux下oracle数据库定时备份
  • 原文地址:https://www.cnblogs.com/muronglin/p/hgoi-20191106.html
Copyright © 2020-2023  润新知