2016青岛网络赛、

1001

找出第一个 2a3b5c7d   (a,b,c,否是非负整数) 大于等于n的数

莫名其妙打表过、

#include<cmath>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
typedef __int64 ll;
ll num[100000];
ll quick(ll a, ll b){
	ll res=1;
	while(b){
		if(b&1)	res*=a;
		a=a*a;
		b>>=1;
	}
	return res;
}
int Get(ll a, ll b){
	if(a>1e9&&b>1e9)	return 20;
	int ans=0,res=0;
	int c=a*b;
	while(a){
		a/=10;
		res++;
	}
	while(b){
		b/=10;
		res++;
	}
	while(c){
		c/=10;
		ans++;
	}
	return min(ans, res);
}
int main(){
	//printf("%I64d\n", quick(3, 19));
	//printf("%I64d\n", quick(5, 13));
	//printf("%I64d\n", quick(7, 11));
	num[0]=1;
	int count=1;
	for(ll i,j,k,l=0; l<31; ++l)
		for(k=0; k<19; ++k)
			for(j=0; j<13; ++j)
				for(i=0; i<11; ++i){
					ll a=quick(2, l);
					ll b=quick(3, k);
					ll c=quick(5, j);
					ll d=quick(7, i);
					if(Get(a, b)+Get(c, d)>=14)	break;
					num[count++]=a*b*c*d;
				}
	//printf("%d\n", count);
	sort(num, num+count);
	int t;scanf("%d",&t);
	while(t--){
		int n;scanf("%d",&n);
		printf("%I64d\n", num[lower_bound(num, num+count, n)-num]);
	}
	return 0;
}

1002

求  1/(k*k) k从1到n的和、 看清题目只要求保留5位小数,所以打表到1e6才够了、少一点好像不行、 因为后面叠加的数值还是会加上来、所以尽可能开的一点

#include<stdio.h>
#include<cstring>
double num[1000000+2];
char s[1000000];
int main(){
	num[1] = 1.0;
	for(long long i=2; i<=1e6; ++i)
		num[i]=num[i-1]+1.0/(i*i);
	int n;
	while(scanf("%s",s)!=EOF){
		if(strlen(s)>6)	{
			printf("%.5lf\n", num[1000000]);
			continue;
		}
		int ans=0;
		for(int i=0; i<strlen(s); ++i)
			ans=ans*10+s[i]-'0';
		printf("%.5lf\n", num[ans]);
	}
	return 0;
}


1006

题意:nnn个点mmm条无向边的图,找一个欧拉通路/回路P0,P1,..PmP_0, P_1, .. P_mP0,P1,..Pm(PiP_iPi是节点标号),使得aP0⊕aP1⊕..⊕aPma_{P_0} \oplus a_{P_1} \oplus .. \oplus a_{P_m}aP0aP1..aPm最大。输出这个值。

题解:由欧拉路性质,奇度点数量为0或2。一个节点被进一次出一次,度减2,产生一次贡献,因此节点uuu的贡献为(⌊degreeu2⌋ mod 2)∗au(\lfloor \frac {degree_u}{2} \rfloor\text{ mod }2) * a_u(2degreeu mod 2)au欧拉回路的起点贡献多一次,欧拉通路的起点和终点贡献也多一次。因此如果是欧拉回路的话枚举一下起点就好了。

<span style="color:#000000;">#include<cmath>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
typedef __int64 ll;
const int qq = 1e5+10; 
int w[qq];
int vis[qq];
int pre[qq];
int find(int x){
	return x==pre[x]?x:pre[x]=find(pre[x]);
}
int main(){
	int t;scanf("%d",&t);
	while(t--){
		int n,m;scanf("%d%d",&n,&m);
		for(int i=1; i<=n; ++i)	scanf("%d", w+i);
		int a,b;
		for(int i=0; i<m; ++i){
			scanf("%d%d",&a,&b);
			vis[a]++,vis[b]++;
		}
		int k=0;
		for(int i=1; i<=n; ++i)	if(vis[i]%2==1)	k++;
		if(k==0||k==2){
			int res=0;
			for(int i=1; i<=n; ++i)
				if(vis[i]!=0)	res^=((vis[i]+1)/2%2)*w[i];  //加1保证奇度顶点产生的贡献计算正确,对偶度顶点没有影响
			if(k==2)	printf("%d\n", res);
			else{
				int maxn=-1;
				for(int i=1; i<=n; ++i)
					maxn = max(maxn, res^w[i]);
				printf("%d\n", maxn);
			}
		}
		else	printf("Impossible\n");
		memset(vis, 0, sizeof(vis));
	}
	return 0;
}</span>


这题我比赛的时候没做出来真有点可惜的、  也尝试着去分析了奇度顶点和偶度顶点,也知道应为要遍历所有的边所以那个最大值在k=2的情况下是一个定值,就是没想到去算每一个点的贡献值...   对这类题大致也有了个了解吧、


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值