今天有人品爆发,240分,但是第三题没特判,第一题没用高精度也是可以GG的…… 明天就是NOIP了,高一党就全当体会一下吧!(P.S.今天有两个高一的来考试(不听劝啊~),于是乎……但愿没影响到他们考试的心情)
没错,这次的每日推荐就是游戏王!!! 从小学二年级开始,我看见了游戏王的起起伏伏,也经历了从萌新到菜鸟,再到现在的一般般的水平,用游戏王作为我今年noip的最后一份推荐,就是想贯彻游戏王决斗中除强大的计算外更吸引我的精神,never give up!! 所以这次就以一句帅气的话来告诉世界,高一党有我在,而我也一定要创造奇迹!!!!(这flag立的………………) than :: 所列哇多噶那!!!(千星大大快更新!!!!)
背景描述:
一切死亡都有冗长的回声 —— 《一切》北岛
给定一个N个元素的序列A, 定义Bi = (Ai and A1) + (Ai and A2) + (Ai and A3)+ …… + (Ai and An) 定义Ci = (Ai or A1) + (Ai or A2) + … + (Ai or An) 求B和C序列。 输入格式: 第一行一个整数N表示序列长度 接下来一行N个整数, 第i个整数为Ai 输出格式: 第一行N个整数输出B序列 第二行N个整数输出C序列
样例输入: 4 3 5 1 1 样例输出: 6 8 4 4 16 22 10 10 数据规模: 对于50%的数据, N <= 1000 对于100%的数据, N <= 100000, Ai <= 100000 注意事项: 输入量较大, 请使用比较快的例如scanf的读入方式, 最好不要采用cin。//使用读入优化readin();注:template< class T >
第一题: 考虑每一位对每个数的贡献, 令cnt[i]为二进制第i位为1的数的个数。 如果第j个数, 第i位为1, 那么第i位对Bj的贡献为cnt[i] * (1 << i), 对Cj的贡献 为n * (1 << i) 否则, 对Bj的贡献为0, 对Cj的贡献为cnt[i] * (1 << i) 复杂度N*logV, V代表值域 题解已经写得很清晰了……小编就不再赘述了。
呜呜呜~~没有标答快……
#include<set> #include<list> #include<deque> #include<queue> #include<cmath> #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #include<cstdlib> #include<string> #include<vector> #include<ctime> #include<stack> #include<map> #define Li(x) x<<1 #define Ri(x) x<<1|1 #define clr(x) memset((x),0,sizeof(x)) #define cld(x) memset((x),127/2,sizeof(x)) #define smin(x,y) x=min(x,y) #define smax(x,y) x=max(x,y) #define smin(x,y) x=min(x,y) #define fmax(x,y,z) max(x,max(z,y)) #define fmin(x,y,z) min(x,min(z,y)) #define res(i,x,y) for(int i=x;i<=y;i++) #define rez(i,x,y) for(int i=x;i>=y;i--) #define resl(i,x,y) for(ll i=x;i<=y;i++) #define rezl(i,x,y) for(ll i=x;i>=y;i--) #define INF 2100000000 #define MOD 1000000007 #define ll long long #define N 200010 #define P 65536 #ifdef win32 #define AUTO "%I64d" #else #define AUTO "%lld" #endif using namespace std; template <class T> inline void readin(T &resez){ static char ch; while((ch=getchar())<'0'||ch>'9'); resez=ch-48; while((ch=getchar())>='0'&&ch<='9') resez=resez*10+ch-48; } const ll M = 1e5+10; ll n,num[21],s[M],a,C[M],B[M],cnt[21]; ll power(ll a,ll b){ ll ans=1; while(b){ if(b%2==1){ ans=ans*a; } a=a*a; b/=2; } return ans; } int main(){ freopen("beleive.in","r",stdin); freopen("believe.out","w",stdout); readin(n); resl(i,1,n){ readin(a); resl(j,0,17){ if((1<<j)&a) num[j]++; else cnt[j]++; } s[i]=a; } resl(i,1,n){ resl(j,0,17){ if((1<<j)&s[i]){ B[i]+=power(2,j)*(num[j]); } } cout<<B[i]<<' '; } printf("\n"); resl(i,1,n){ resl(j,0,17){ if((1<<j)&s[i]) { C[i]+=power(2,j)*(num[j]+cnt[j]); } else{ C[i]+=power(2,j)*(num[j]); } } cout<<C[i]<<' '; } return 0; }这次标答的却比所有人都优……
//#include <bits/stdc++.h> #include <iostream> #include <cstdio> #ifdef WIN32 #define LLD "%I64d" #else #define LLD "%lld" #endif using namespace std ; int n ; const int MAXN = 100010 ; typedef long long LL ; int cnt[MAXN], a[MAXN] ; LL b[MAXN], c[MAXN]; int main() { freopen("beleive.in", "r", stdin) ; freopen("believe.out", "w", stdout) ; scanf("%d", &n) ; for (int i = 1; i <= n; i ++) scanf("%d", &a[i]) ; for (int i = 1; i <= n; i ++) { for (int j = 0; j < 20; j ++) { if ((a[i] >> j) & 1) cnt[j] ++ ; } } for (int i = 1; i <= n; i ++) { for (int j = 0; j < 20; j ++) { if ((a[i] >> j) & 1) { b[i] += 1LL * cnt[j] * (1 << j) ; c[i] += 1LL * n * (1 << j) ; } else { c[i] += 1LL * cnt[j] * (1 << j) ; } } } for (int i = 1; i <= n; i ++) { printf(LLD "%c", b[i], (i == n ? 10 : ' ')) ; } for (int i = 1; i <= n; i ++) { printf(LLD "%c", c[i], (i == n ? 10 : ' ')) ; } }背景描述:
不是一切深渊都是灭亡 不是一切灭亡都覆盖在弱者的头上 ——《这也是一切》 舒婷
有N个透明的盒子, 每个盒子里面有两个不同颜色的球, 总共有M种颜色。 Alice和Bob又在玩游戏, 具体的, Alice会从N个盒子里面选出若干个, Bob再从Alice选出的盒子里面选出一些(不能不选), 如果在Bob选出的盒子中, 每个颜色的球都总共出现了偶数次(0次也是偶数次), 那么Bob胜利, 否则Alice胜利 在Alice和Bob都足够聪明的情况下, Alice想知道自己在能够获胜的前提下, 第一次最多可以选出几个盒子 输入格式: 第一行有两个整数N和M, 意义如题 接下来N行, 第i+1行两个整数表示第i+1个盒子里面的两个球分别是什么颜色的 输出格式: 一行一个整数表示Alice最多可以选多少个盒子
样例输入: 3 3 1 2 2 3 2 3 样例输出: 2 数据规模: 对于30%的数据, N <= 10 对于50%的数据, N <= 20 对于100%的数据, N <= 100000, M <= 2N
第二题: 将每一种颜色的球看成点, 那么一个盒子就是一条连接两个点的边。 选出的盒子如果构成了环, 那么Bob胜, 否则Alice胜 也就是说我们现在要选出尽量多的边, 使得不存在环, 直接并查集即可 并查集在此处
小编是通过建图来解决的………………很慢…………
#include<set> #include<list> #include<deque> #include<queue> #include<cmath> #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #include<cstdlib> #include<string> #include<vector> #include<ctime> #include<stack> #include<map> #define Li(x) x<<1 #define Ri(x) x<<1|1 #define clr(x) memset((x),0,sizeof(x)) #define cld(x) memset((x),127/2,sizeof(x)) #define smin(x,y) x=min(x,y) #define smax(x,y) x=max(x,y) #define smin(x,y) x=min(x,y) #define fmax(x,y,z) max(x,max(z,y)) #define fmin(x,y,z) min(x,min(z,y)) #define res(i,x,y) for(int i=x;i<=y;i++) #define rez(i,x,y) for(int i=x;i>=y;i--) #define INF 2100000000 #define MOD 1000000007 #define ll long long #define N 200010 #define P 65536 #ifdef win32 #define AUTO "%I64d" #else #define AUTO "%lld" #endif using namespace std; const int M = 2e5+5; int n,m,a,b,be[M],tot,num[M],ans; template <class T> inline void readin(T &resez){ static char ch; while((ch=getchar())<'0'||ch>'9'); resez=ch-48; while((ch=getchar())>='0'&&ch<='9') resez=resez*10+ch-48; } struct Edge{ int from,to; int belong; }edge[M]; vector<int> g[M]; void dfs(int s){ for (int i=0;i<g[s].size();i++){ int v=g[s][i]; if(!be[v]){ be[v]=be[s]; dfs(v); } } } int main(){ freopen("heart.in","r",stdin); freopen("haert.out","w",stdout); cin>>n>>m; res(i,1,n){ readin(a);readin(b); g[a].push_back(b);g[b].push_back(a); edge[i].to=a;edge[i].from=b; } res(i,1,m){ if(!be[i])be[i]=++tot; dfs(i); } res(i,1,m)num[be[i]]++; res(i,1,tot)ans+=num[i]-1; cout<<ans; return 0; }反正能AC
但是标答或者说是更快的方法是李ys大神所用的并查集(Kruskal)就可以达到最快!!!
#include<iostream> #include<cstdio> #include<ctime> #include<algorithm> using namespace std; const int MAX=100000*4; int fa[MAX],ans,n,m; int findfa(int k) { if (fa[k]==k) return k; return fa[k]=findfa(fa[k]); } inline int read() { char x=(char)getchar(); int re=0; while (x<='9'&&x>='0') { re=re*10+x-48; x=getchar(); } return re; } int main() { freopen("heart.in","r",stdin); freopen("haert.out","w",stdout); n=read();m=read(); for (int i=1;i<=m;i++) fa[i]=i; for (int i=1;i<=n;i++) { int x=read(),y=read(); int f1=findfa(x); int f2=findfa(y); if (f1!=f2) { fa[f1]=f2; ans++; } } printf("%d",ans); return 0; }背景描述: 黑夜给了我黑色的眼睛 我却用它寻找光明 ——《一代人》 顾城 已知一个N个元素的非负整数序列A, 定义Bi = (Ai and A1) + (Ai and A2) + (Ai and A3)+ …… + (Ai and An) 定义Ci = (Ai or A1) + (Ai or A2) + … + (Ai or An) 给出B和C序列, 构造一个满足条件的A序列, 如果没有, 输出-1 输入格式: 第一行一个整数N。 接下来一行N个整数表示B序列 接下来一行N个整数表示C序列 输出格式: 如果有解, 输出一行N个整数表示你构造的A序列, SPJ很脆弱, 所以你构造的序列每个整数必须在[0,8191]这个区间内, 我们保证如果有解, 那么一定存在一个解满足每个元素均在[0,8191]内 否则输出-1
样例输入: 4 6 8 4 4 16 22 10 10 样例输出: 3 5 1 1 数据规模: 对于30%的数据, N = 2 对于70%的数据, N <= 200 对于100%的数据, N <= 100000, Bi , Ci<= 1000000000
第三题: 第三题是第一题倒过来。 注意到对于任意两个非负整数A, B。 A and B + A or B = A + B 于是Bi+Ci = A1 + A2 + ….. + An + Ai * n 我们可以把所有数求和, 得到Ai的和, 记为sum, 再对每个数用Bi+Ci-sum / n 可以得到Ai 最后跑一遍第一题判定一下是否合法即可 值域在0到8191只是为了随机数据随出来B和C都在1e9以内, 没有实际意义
听小编一言,上诉都是渣渣!!!!! 看小编的代码!!!!!
A+B=A&B+A|B
#include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> #define name "problem" #define maxn 100009 typedef long long ll; using namespace std; ll b[maxn],c[maxn],a[maxn]; void get(ll &y) { y=0; char x=getchar(); while('0'>x||x>'9') x=getchar(); while('0'<=x&&x<='9') { y=y*10+x-'0'; x=getchar(); } } int main() { freopen(name".in","r",stdin); freopen(name".out","w",stdout); ll n; get(n); ll sum=0; for(int i=1;i<=n;i++) { get(b[i]); sum+=b[i]; } for(int i=1;i<=n;i++) { get(c[i]); sum+=c[i]; } if(sum%(2*n)==0) sum/=2*n; else { cout<<-1<<endl; return 0; } for(int i=1;i<=n;i++) { if((b[i]+c[i]-sum)%n==0) a[i]=(b[i]+c[i]-sum)/n; else { cout<<-1<<endl; return 0; } } for(int i=1;i<=n;i++) { cout<<a[i]<<(i==n ? "\n" : " "); } }今天也无力回天了…… 面对现实吧,小编自己只是个渣渣…………………… 然后预祝所有的OIer考试顺利!!! (自己更加顺利!!!!!) (没有高精度!!!) (今天忘发图!!!)