• 10.29 考试总结


    T1 birthday

    Desprition

    两种操作,第一种操作把 (l,r) 的区间的颜色赋为 (x),第二个操作询问 (l,r) 这一段区间不同颜色的个数。

    (n,mleq 10^5,kleq 30) (k) 为颜色个数。

    一开始每个点的颜色都为零

    solution

    mdzz考试的时候题面没说清楚,直接把我们机房一堆人都坑了。

    本来打了正解,结果直接变成 (25) 分。

    当时我的做法想的是对于每个叶子节点维护一个二进制数,(0/1) 表示这个颜色是否出现过。

    (up) 的时候直接把左右儿子的二进制数或一下就行。

    剩下的就是普通的区间覆盖和区间查询问题。线段树维护一下就可以。

    Code

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    using namespace std;
    const int N = 1e5+10;
    int n,m,k,l,r,x,ans;
    inline int read()
    {
    	int s = 0,w = 1; char ch = getchar();
    	while(ch < '0' || ch > '9'){if(ch == '-') w = -1; ch = getchar();}
    	while(ch >= '0' && ch <= '9'){s = s * 10 + ch - '0'; ch = getchar();}
    	return s * w;
    }
    struct Tree
    {
    	int lc,rc;
    	int sum,tag;
    }tr[N<<2];
    #define l(o) tr[o].lc
    #define r(o) tr[o].rc
    #define sum(o) tr[o].sum
    #define tag(o) tr[o].tag
    void up(int o)
    {
    	sum(o) = sum(o<<1) | sum(o<<1|1);
    }
    void cover(int o,int val)
    {
    	sum(o) = val;
    	tag(o) = val;
    }
    void down(int o)
    {
    	if(tag(o))
    	{
    		cover(o<<1,tag(o));
    		cover(o<<1|1,tag(o));
    		tag(o) = 0;
    	}
    }
    void build(int o,int L,int R)
    {
    	l(o) = L, r(o) = R;
    	if(L == R)
    	{
    		sum(o) = 1;
    		return;
    	}
    	int mid = (L + R)>>1;
    	build(o<<1,L,mid);
    	build(o<<1|1,mid+1,R);
    	up(o);
    }
    void chenge(int o,int L,int R,int val)
    {
    	if(L <= l(o) && R >= r(o)) 
    	{
    		cover(o,val);
    		return;
    	}
    	down(o);
    	int mid = (l(o) + r(o))>>1;
    	if(L <= mid) chenge(o<<1,L,R,val);
    	if(R > mid) chenge(o<<1|1,L,R,val);
    	up(o);
    }
    int query(int o,int L,int R)
    {
    	int res = 0;
    	if(L <= l(o) && R >= r(o)) return sum(o);
    	down(o);
    	int mid = (l(o) + r(o))>>1;
    	if(L <= mid) res |= query(o<<1,L,R);
    	if(R > mid) res |= query(o<<1|1,L,R);
    	return res;
    }
    int main()
    {
    //	freopen("birthday.in","r",stdin);
    //	freopen("birthday.out","w",stdout);
    	n = read(); k = read(); m = read();
    	build(1,1,n);
    	for(int i = 1; i <= m; i++)
    	{
    		char opt; cin>>opt;
    		l = read(); r = read();
    		if(l > r) swap(l,r);
    		if(opt == 'C')
    		{
    			x = read();
    			chenge(1,l,r,(1<<(x-1)));
    		}
    		else
    		{
    			int tmp = query(1,l,r); ans = 0;
    			for(int j = 1; j <= k; j++) if(tmp & (1<<(j-1))) ans++;
    			printf("%d
    ",ans);
    		}
    	}
    	fclose(stdin); fclose(stdout);
    	return 0;
    }
    

    T2 number

    Desprition

    给你一个数 (n) ,让你构造出一个数满足这个数只由 (4,7) 构成,同时 (4,7) 出现的次数相等。

    请输出大于等于 (n) 的第一个满足条件的数。

    (mleq 10^{100000},Tleq 100)

    solution

    正解是搜索,你敢信。

    (1e5) 的数据范围你告诉搜索能过???,我直接亦或。

    考试的时候打了个按位贪心,结果发现要考虑很多情况,直接傻了,调了半天没有调出来。

    显然当 (n) 为奇数的时候 的 则答案长度必定为 (n+1) ,且是类似于 (44444...7777) 的形式。

    对于 (n) 为偶数的时候,答案长度可能为 (n,n+2) ,但当长度为 (n+2) 的时候,也一定是 (44444...7777) 的形式。

    然后,我们就可以搜索每一位上填 (4) 还是 (7) ,同时记录下还需要填的 (4,7) 的个数。

    以及是否比原数大,如果你原数大的话,答案肯定是 先把剩下的 (4) 填完,在去填 (7).

    一直搜下去就可以。

    复杂度 (O(玄学))

    Code

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    int n,four,seven,flag;
    char ans[100010],ch[100010];
    bool dfs(int x,int four,int seven,int flag)//four 记录剩下的 4的个数,seven记录剩下的7的个数,flag表示是否比原数大
    {
    	if(x >= n+1) return 1;
    	if(flag)
    	{
    		for(int i = 0; i < four; i++) ans[x + i] = '4';
    		for(int i = 0; i < seven; i++) ans[x+four+i] = '7';
    		return 1;
    	}
    	if(ch[x] <= '4' && four && dfs(x+1,four-1,seven,ch[x] < '4')){ ans[x] = '4'; return 1;}//能填四就填四
    	if(ch[x] <= '7' && seven && dfs(x+1,four,seven-1,ch[x] < '7')) { ans[x] = '7'; return 1;}//否则就填7
    	return 0;
    }
    int main()
    {
    	freopen("number.in","r",stdin);
    	freopen("number.out","w",stdout);
    	while(scanf("%s",ch+1) != EOF)
    	{
    		n = strlen(ch+1);
    		if(n % 2 || !dfs(1,n>>1,n>>1,0))
    		{
    			if(n %2 == 1) n++;
    			else n += 2;
    			for(int i = 1; i <= (n>>1); i++) ans[i] = '4';
    			for(int i = (n>>1)+1; i <= n; i++) ans[i] = '7';
    		}
    		for(int i = 1; i <= n; i++) cout<<ans[i];
    		printf("
    ");
    	}
    	fclose(stdin); fclose(stdout);
    	return 0;
    }
    

    T4 肉

    Desprition

    两只狗在大街上发现了 (T) 大块肉。狐狸跑过来想帮它们分肉,可有了上次被坑的经历,两只狗拒绝它,选择自己分。对于块肉,甲狗和乙狗把肉一扯开,甲狗会得 (n) 千克的肉,乙狗得$ m$ 千克的肉,少肉的那条狗会抢对方的肉,使自己的肉多一倍。抢了 (k) 次后两条狗都累了,那么此时少肉的一方剩下多少千克的肉呢?(注:若两狗的肉一样多,甲狗会主动抢乙狗的肉)

    对于30% 的数据 (kleq 10000)

    对于60% 的数据 (n,mleq100000)

    对于100% 的数据 (n,m,kleq 10^9)

    sloution

    阴间题。死也不会想到做法,看了题解一看就会的那种。

    一个结论就是答案为 (min(n imes 2^k,m imes 2^k))

    证明一下,每次操作 (n+m) 的总和是不变的,所以我们可以把所有的操作看成是在 模 (n+m) 的意义下进行的。

    (n>m)。对于 (m) ,操作后变为 (m imes 2), (n) 则变为 (n-m)

    然后考虑 (n-m = b) 怎么转化为 (n imes 2 mod (n+m) = b)

    把模转化成 (ka+b) 的形式可以写成 (2 imes n = k(n+m) + b)

    然后因为 (nleq n+m) 所以 (2 imes n leq 2 imes(n+m))

    所以 (k) 的系数为 (1)

    然后就转化为 (n-m -b = 2 imes n - (n+m) - b)

    化简一下柿子可以写成 (n-m -b = n-m-b) ,发现等式两边其实是等价的。

    所以每次操作可以看成 (n imes 2,m imes 2) ,然后快速幂处理一下就行。

    Code

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    using namespace std;
    #define int long long
    int T,n,m,k,p;
    inline int read()
    {
    	int s = 0, w = 1; char ch = getchar();
    	while(ch < '0' || ch > '9'){if(ch == '-') w = -1; ch = getchar();}
    	while(ch >= '0' && ch <= '9'){s = s * 10 + ch - '0'; ch = getchar();}
    	return s * w;
    }
    int ksm(int a,int b)
    {
    	int res = 1;
    	for(; b; b >>= 1)
    	{
    		if(b & 1) res = res * a % p;
    		a = a * a % p;
    	}
    	return res;
    }
    signed main()
    {
    	freopen("scramble.in","r",stdin);
    	freopen("scramble.out","w",stdout);
    	T = read();
    	while(T--)
    	{ 
    		n = read(); m = read();  k = read();
    		p = n+m;
    		int base = ksm(2,k);
    		printf("%lld
    ",min(n * base % p, m * base % p));
    	}
    	fclose(stdin); fclose(stdout);
    	return 0;
    }
    }
    
  • 相关阅读:
    ihaiLjEUSx
    表达式的逆波兰式转化模板
    运算表达式求值模板
    程序员花式拜年脚本
    vbs脚本实现自动打字祝福&搞笑
    MFC实现红黑砖块
    vbs脚本实现qq定时发消息(初级)
    打包java程序生成exe
    webpack配置
    vue路由
  • 原文地址:https://www.cnblogs.com/genshy/p/13899594.html
Copyright © 2020-2023  润新知