• [PA2014] [BZOJ 3709]~[BZOJ 3719] 合集


    今天起尝试做套题喵~ (当然是因为被最大流的题目弄得恶心死了)

    一共是 10 道题一道一道做 预计 3~4 内做完 尽情期待

    [BZOJ 3709]Bohater

    一眼就能感受到贪心的气息

    因为很直观地,能加血的怪先打掉是不二法则

    所以把怪分为两类: 能加血的和要掉血的

    前者按伤害升序排序,算出最大血量

    但后者要怎么搞让我很是郁闷~一开始是按伤害降序的,结果秒 WA 了

    想想也是 Z=1000 怪1: a=998 d=1  怪2: a=100 d=99 你说先打哪只?

    看来和回血量也是有关系的,事实上按回血量降序排序即可

    但为什么呢?

    因为最后血量是固定的,所以可以看成从最后血量开始,吐出血瓶,加上打怪时的血量一路逆推(此时怪的 d 是 a ,a 是 d) 问能否打败所有怪

    然后就变成和前面一样的问题了

    就这么 A 掉了,看来凡事都要反过来想想才行 (顺便提醒一句,此题 z 变量要开 long long)

    #include <cstdio>
    #include <algorithm>
    const int sizeOfMonster=100025;
    
    inline int getint()
    {
    	register int num=0;
    	register char ch;
    	do ch=getchar(); while (ch<'0' || ch>'9');
    	do num=num*10+ch-'0', ch=getchar(); while (ch>='0' && ch<='9');
    	return num;
    }
    inline void putint(int num)
    {
    	char stack[15];
    	register int top=0;
    	if (num==0) stack[top=1]='0';
    	for ( ;num;num/=10) stack[++top]=num%10+'0';
    	for ( ;top;top--) putchar(stack[top]);
    	putchar(' ');
    }
    
    struct node
    {
    	int id, d, a;
    	inline node():id(0), d(0), a(0) {}
    	inline node(int _id, int _d, int _a):id(_id), d(_d), a(_a) {}
    };
    int n; long long z;
    int t1, t2;
    node add[sizeOfMonster], sub[sizeOfMonster];
    inline bool cmpForAdd(node x, node y) {return x.d<y.d;}
    inline bool cmpForSub(node x, node y) {return x.a>y.a;}
    
    int main()
    {
    	register int i;
    
    	n=getint(), z=getint();
    	for (i=1;i<=n;i++)
    	{
    		int d=getint(), a=getint();
    		if (d<=a) add[t1++]=node(i, d, a);
    		else sub[t2++]=node(i, d, a);
    	}
    	std::sort(add, add+t1, cmpForAdd);
    	for (i=0;i<t1;i++)
    	{
    		if (z<=add[i].d) break;
    		z=z+add[i].a-add[i].d;
    	}
    
    	if (i<t1) {printf("NIE
    "); return 0;}
    
    	std::sort(sub, sub+t2, cmpForSub);
    	for (i=0;i<t2;i++)
    	{
    		if (z<=sub[i].d) break;
    		z=z+sub[i].a-sub[i].d;
    	}
    
    	if (i<t2) {printf("NIE
    "); return 0;}
    
    	printf("TAK
    ");
    	for (i=0;i<t1;i++) putint(add[i].id);
    	for (i=0;i<t2;i++) putint(sub[i].id);
    	putchar('
    ');
    
    	return 0;
    }
    

    [BZOJ 3713]Iloczyn

    一道很有神题外表的水题……  直接暴力就好了

    话说就算 t<106 ,n_i<1018 也没有多大差啊~

    因为斐波那契数列是以指数级别增长的,小于 109 的斐波那契数只有 45 个

    真是想怎么搞怎么搞的节奏……

    #include <cstdio>
    #include <cmath>
    #include <map>
    const int sizeOfTot=32000;
    const int sizeOfNum=1000000000;
    
    inline int getint()
    {
    	register int num=0;
    	register char ch;
    	do ch=getchar(); while (ch<'0' || ch>'9');
    	do num=num*10+ch-'0', ch=getchar(); while (ch>='0' && ch<='9');
    	return num;
    }
    inline void putint(bool num)
    {
    	if (num) putchar('T'), putchar('A'), putchar('K');
    	else putchar('N'), putchar('I'), putchar('E');
    	putchar('
    ');
    }
    
    int t;
    int tot, f[sizeOfTot];
    std::map<int, bool> exist;
    inline void prepare();
    inline bool check(int);
    
    int main()
    {
    	prepare();
    	for (t=getint();t;t--)
    		putint(check(getint()));
    
    	return 0;
    }
    inline void prepare()
    {
    	register int i=0;
    	f[0]=0; f[1]=1; exist[0]=exist[1]=true;
    	for (i=2;(f[i]=f[i-1]+f[i-2])<sizeOfNum;i++)
    		exist[f[i]]=true;
    	tot=i;
    }
    inline bool check(int x)
    {
    	if (x==0) return true;
    	int lim=static_cast<int>(sqrt(x+0.5));
    	for (int i=1;i<tot && f[i]<=lim;i++)
    		if (x%f[i]==0 && exist[x/f[i]])
    			return true;
    	return false;
    }
    

    [BZOJ 3715]Lustra

    我很高兴又是一道水题~

    显然满足条件的工厂的 w1 ,h1 是所有 w1,h1 值的最小值(之一) w2 ,h2 是所有 w2,h2 值的最大值(之一)

    乱搞搞一下就好了

    顺便说一句,此题卡快排 当然了你是在弃疗吗?为什么非用快排不可呢?

    #include <cstdio>
    const int sizeOfMirror=100025;
    
    inline int getint()
    {
    	register int num=0;
    	register char ch;
    	do ch=getchar(); while (ch<'0' || ch>'9');
    	do num=num*10+ch-'0', ch=getchar(); while (ch>='0' && ch<='9');
    	return num;
    }
    inline void putint(bool num)
    {
    	if (num) putchar('T'), putchar('A'), putchar('K');
    	else putchar('N'), putchar('I'), putchar('E');
    	putchar('
    ');
    }
    
    struct mirror
    {
    	int w1, w2, h1, h2;
    	inline void get() {w1=getint(); w2=getint(); h1=getint(); h2=getint();}
    };
    
    int t, n;
    inline bool cmp(mirror a, mirror b)
    {
    	if (a.w1>b.w1) return false; if (a.w1<b.w1) return true;
    	if (a.w2<b.w2) return false; if (a.w2>b.w2) return true;
    	if (a.h1>b.h1) return false; if (a.h1<b.h1) return true;
    	if (a.h2<b.h2) return false; if (a.h2>b.h2) return true;
    	return true;
    }
    mirror M[sizeOfMirror];
    
    int main()
    {
    	register int i, k;
    
    	for (t=getint();t;t--)
    	{
    		n=getint();
    		for (i=0;i<n;i++) M[i].get();
    		k=0;
    		for (i=1;i<n;i++) if (cmp(M[i], M[k]))
    			k=i;
    		for (i=0;i<n;i++)
    			if (M[i].w1<M[k].w1 || M[i].w2>M[k].w2 || M[i].h1<M[k].h1 || M[i].h2>M[k].h2)
    				break;
    		putint(i>=n);
    	}
    
    	return 0;
    }
    

     
    [BZOJ 3714]Kuglarz

    这一题着实让我想了不少时间…… 然后等我意识到怎么做时,又觉得自己的智商下滑了喵(不过我可是独立思考的,求表扬!)

    一下子就想到了某最小生成树的做法,因为一段区间内的小球数的奇偶其实就是一个异或方程

    我们只需要 n 个线性不相关的方程就可以算出每个 x (即位置 i 是否有小球)

    我们把所有的边都排序后选出前 n 个互不线性相关的即可

    但如何判断这现方程是否和之前的方程线性相关呢?让我纠结了好久……

    然后,我发现了一个非常简单的做法——并查集

    每一个线段都有首尾两个端点,如果之前的有数条相连的线段的首尾也是这两个端点,那么该方程与之前的方程线性相关(这里大家就感性YY一下吧233)

    没理解的还是看看我的代码好了……

    #include <cstdio>
    #include <algorithm>
    const int sizeOfSegment=4000004;
    
    int n, m;
    long long ans;
    inline int getint();
    inline void putint(long long);
    
    int a[sizeOfSegment];
    int l[sizeOfSegment], r[sizeOfSegment], c[sizeOfSegment];
    int f[sizeOfSegment];
    inline bool cmp(int i, int j) {return c[i]<c[j];}
    int find(int u) {return f[u]==u?u:f[u]=find(f[u]);}
    inline void merge(int u, int v) {u=find(u); v=find(v); if (u==v) return ; f[v]=u;}
    
    int main()
    {
    	n=getint();
    	for (int i=1;i<=n;i++)
    		for (int j=i;j<=n;j++)
    			a[m]=m, l[m]=i, r[m]=j+1, c[m++]=getint();
    	for (int i=1;i<=n+1;i++) f[i]=i;
    	std::sort(a, a+m, cmp);
    
    	int k=0;
    	for (int i=0;i<m;i++)
    	{
    		if (find(l[a[i]])!=find(r[a[i]]))
    		{
    			ans+=c[a[i]];
    			if (++k==n) break;
    		}
    		merge(l[a[i]], r[a[i]]);
    	}
    
    	putint(ans);
    
    	return 0;
    }
    inline int getint()
    {
    	register int num=0;
    	register char ch;
    	do ch=getchar(); while (ch<'0' || ch>'9');
    	do num=num*10+ch-'0', ch=getchar(); while (ch>='0' && ch<='9');
    	return num;
    }
    inline void putint(long long num)
    {
    	char stack[20];
    	register int top=0;
    	if (num==0) stack[top=1]='0';
    	for ( ;num;num/=10) stack[++top]=num%10+'0';
    	for ( ;top;top--) putchar(stack[top]);
    	putchar('
    ');
    }
    
  • 相关阅读:
    2017-2018-2 20179225《网络攻防与实践》 第5周作业
    NetSec2019 20165327 Exp3 免杀原理与实践
    NetSec2019 20165327 Exp2 后门原理与实践
    NetSec2019 20165327 Exp1 PC平台逆向破解
    NetSec2019 20165327 Exp0 Kali安装 Week1
    实验五 通讯协议设计
    2018-2019-1 20165307 20165327 20165332 实验四 外设驱动程序设计
    2018-2019-1 20165327 《信息安全系统设计基础》第八周学习总结
    实现mypwd&mybash&myod&读者写者
    2018-2019-1 20165327 实验三 实时系统
  • 原文地址:https://www.cnblogs.com/dyllalala/p/3973162.html
Copyright © 2020-2023  润新知