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 */
2019ICPC徐州站重现赛——ACFM题解
猜你喜欢
转载自blog.csdn.net/qq_43472263/article/details/104717044
今日推荐
周排行