2019ICPC徐州站重现赛——ACFM题解

比赛链接:https://www.jisuanke.com/contest/5529?view=challenges

 A - Cat

题解:先打出异或前缀和的表,不难发现当在偶数位置pos时,[pos,pos+3]这些数的异或和为0,这意味着中间的序列可以每四个四个的连一起,因为他们异或和的值为0,因此我们就可枚举开头和结尾的位置,并维护最大长度。

代码实现:

#include<bits/stdc++.h>
#define ll long long
using namespace std;
ll check(ll l,ll r){
    if(l>r) return 0;
    ll sum=0;
    if(r-l+1<=10){
        for(ll i=l;i<=r;i++) sum^=i;
        return sum;
    }
    else{
        while(l%4!=0) sum^=l,l++;
        while(r%4!=3) sum^=r,r--;
        return sum;
    }
}
int main(){
    int T;
    scanf("%d",&T);
    while(T--){
        ll l,r,s;
        scanf("%lld%lld%lld",&l,&r,&s);
        ll ans=-1;
        for(int i=0;i<=3;i++){
            for(int j=0;j<=3;j++){
                ll L=l+i,R=r-j;
                if(check(L,R)<=s) ans=max(ans,R-L+1);
            }
        }
        printf("%lld\n",ans==0?-1:ans);
    }
    return 0;
}

C - <3 numbers

题解:

如果对质数密度不是很熟悉,那么这道题就不是一道很好想的签到题。

首先我们可以打一个质数分布的表,然后根据质数分布定理( π(x)=x/ln(x) )。

我们可以推出当区间长度大于60的时候,所有区间的质数密度都满足条件,直接输出YES。

否则的话再在小区间里面进行暴力枚举就行了。

代码实现:

#pragma GCC optimize(2)
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<cstdio>
#include<cstdlib>
#include<vector>
#include<map>
#include<set>
#include<stack>
#include<queue>
#define PI atan(1.0)*4
#define E 2.718281828
#define rp(i,s,t) for (register int i = (s); i <= (t); i++)
#define RP(i,t,s) for (register int i = (t); i >= (s); i--)
#define ll long long
#define ull unsigned long long
#define mst(a,b) memset(a,b,sizeof(a))
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define pii pair<int,int>
#define mp make_pair
#define pb push_back
#define debug printf("ac\n");
using namespace std;
inline int read()
{
    int a=0,b=1;
    char c=getchar();
    while(c<'0'||c>'9')
    {
        if(c=='-')
            b=-1;
        c=getchar();
    }
    while(c>='0'&&c<='9')
    {
        a=(a<<3)+(a<<1)+c-'0';
        c=getchar();
    }
    return a*b;
}
const int INF = 0x3f3f3f3f;
const int N = 1e5+7;
bool visited[N];
int prime[N],tot;
void init(){
    long long i,j;
    memset(visited,true,sizeof(visited));
    tot=0;
    visited[1]=0;
    for(i=2;i<N;i++){
        if(visited[i]){
            prime[++tot]=i;
            for(j=i*i;j<N;j+=i) visited[j]=false;
        }
    }
}
bool isprime(int n){
    int i,k=(int)sqrt(double(n));
    for(int i=1;prime[i]<=k;i++)
        if(n%prime[i]==0)
            return 0;
    return 1;
}
int main(){
    init();
    int T=read();
    while(T--){
        int L=read(),R=read();
        if(R-L+1>60) printf("Yes\n");
        else{
            int cnt=0;
            for(int i=L;i<=R;i++) if(isprime(i)) cnt++;
            if(cnt*3<R-L+1) printf("Yes\n");
            else printf("No\n");
        }
    }
    return 0;
}

F - The Answer to the Ultimate Question of Life, The Universe, and Everything.

题解:一看数据范围不难想到可以打表,所以说打表的速度就决定你A这个题的速度,

下面给出一个比较快的打表代码(来自网上大佬)

#include <bits/stdc++.h>
#include <tr1/unordered_map>
using namespace std;
typedef long long ll;
tr1::unordered_map<ll, int> f;
ll g(ll x)
{
	for (ll i = -5000; i <= 5000; i++)
		if (i * i * i == x)
			return i;
}
bool find(int x)
{
	for (ll i = 0; i <= 5000; i++)
		for (long long j = 0; j <= 5000; j++)
			if (f.count(i * i * i + j * j * j + x))
			{
				printf("%lld,%lld,%lld,\n", g(i * i * i + j * j * j + x), -i, -j);
				return true;
			}
			else if (f.count(i * i * i + j * j * j - x))
			{
				//printf("%lld %lld %lld = %d\n",i,j,-g(i*i*i+j*j*j-x),x);
				printf("%lld,%lld,%lld,\n", g(i * i * i + j * j * j - x) == 0 ? 0 : -g(i * i * i + j * j * j - x), i, j);
				return true;
			}
	return false;
}
int main()
{
	freopen("ans.txt", "w", stdout);
	f.clear();
	for (ll i = -5000; i <= 5000; i++)
		f[i * i * i] = 1;
	for (int x = 0; x <= 200; x++)
	{
		//printf("find %d\n",x );
		if (!find(x))
			printf("111111111111,0,0,\n");
		else
			continue;
	}
	return 0;
}

M - kill the tree

题解:一道很不多的树形dp题,考察了树的重心的几条特别重要的性质:

1.一颗树的重心最多有两个

2.一颗树的重心到其他点的距离和最小,如果有两个重心,那么两个重心的距离和 相等。

3.当两个子树合并时,新的树的重心在连接这两个子树重心的链上。

因此根据这几个性质,我们可以求出两个重心连接的链,然后沿着这链往上走,能往上走的前提是距离和可以继续减少,这样保证当前点不是重心,直到走到那个深度比较大的重心,如果这个重心的距离和等于其父亲的距离和,那么他父亲就也是重心。 

代码实现:

#pragma GCC optimize(2)
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<cstdio>
#include<cstdlib>
#include<vector>
#include<map>
#include<set>
#include<stack>
#include<queue>
#define PI atan(1.0)*4
#define E 2.718281828
#define rp(i,s,t) for (register int i = (s); i <= (t); i++)
#define RP(i,t,s) for (register int i = (t); i >= (s); i--)
#define ll long long
#define ull unsigned long long
#define mst(a,b) memset(a,b,sizeof(a))
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define pii pair<int,int>
#define mp make_pair
#define pb push_back
#define debug printf("ac\n");
using namespace std;
inline int read()
{
    int a=0,b=1;
    char c=getchar();
    while(c<'0'||c>'9')
    {
        if(c=='-')
            b=-1;
        c=getchar();
    }
    while(c>='0'&&c<='9')
    {
        a=(a<<3)+(a<<1)+c-'0';
        c=getchar();
    }
    return a*b;
}
const int INF = 0x3f3f3f3f;
const int N = 2e5+7;
int n,m;
struct edge{
    int to,nxt;
}e[N*2];
int tot; 
int head[N*2];
vector<int> h[N];
int p[N],sz[N],deep[N],son[N];
void addEdge(int u,int v){
    e[++tot].nxt=head[u];
    e[tot].to=v;
    head[u]=tot;
}
void update(int rt,int x,int y){
    while(deep[x]>deep[rt]&&sz[rt]-sz[x]>sz[x]) x=p[x];
    while(deep[y]>deep[rt]&&sz[rt]-sz[y]>sz[y]) y=p[y];
    if(deep[x]<=deep[y]) son[rt]=y;
    else son[rt]=x; 
}
void dfs(int u,int fa)
{
    sz[u]=1,son[u]=u;
    p[u]=fa;
    for(int i=head[u];i;i=e[i].nxt)
    {
        int v=e[i].to;
        if(v==fa)continue;
        deep[v]=deep[u]+1;
        dfs(v,u);
        sz[u]+=sz[v];
        update(u,son[u],son[v]);
    }
}
int main(){
    n=read();
    rp(i,1,n-1){
        int x=read(),y=read();
        addEdge(x,y);
        addEdge(y,x);
    }
    deep[1]=1;
    dfs(1,0);
    rp(i,1,n){
        h[i].pb(son[i]);
        if(p[son[i]]&&sz[i]-sz[son[i]]==sz[son[i]]) h[i].pb(p[son[i]]);
        sort(h[i].begin(),h[i].end(),less<int>());
        rp(j,0,h[i].size()-1) printf("%d%s",h[i][j],j == h[i].size() - 1 ? "\n" : " ");
    }
    return 0;
}
/*
6
1 2
1 5
1 3
2 4
2 6
*/
发布了342 篇原创文章 · 获赞 220 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/qq_43472263/article/details/104717044