2017广西邀请赛模拟
HDU 6182 A Math Problem
数学题。。我和老谭都做过,就交给学弟去做。实际上回忆一下计组的知识,
#include<bits\stdc++.h>
#define M(a,b) memset(a,b,sizeof(a))
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
using namespace std;
const int MAXN=100007;
typedef long long LL;
unsigned long long mp[17];
void init()
{
for(unsigned long long i=1;i<=16;i++)
{
unsigned long long ans=1;
for(int j=1;j<=i;j++)
{
ans*=i;
}
mp[i]=ans;
}
}
int main()
{
init();
//for(int i=1;i<=16;i++)
// printf("%d:%llu\n", i, mp[i]);
int ans=0;
unsigned long long n;
while(cin>>n)
{
for(int i=1;i<=15;i++)
{
if(mp[i]<=n)
ans=i;
else break;
}
cout<<ans<<endl;
}
return 0;
}
学弟写A时我在弄C,dfs四元环,简单写了一发MLE。。不知那里写错了了。。学弟找到水题E,求除了某个数以外其他数的and or xor。xor很好办,整体异或在异或被排除的数即可。and和or,数据1e5,暴力统计每一位的1个数,减去特定数字每一位的1,再判断。and某位是1的情况是1的个数==n-1,or某位是1的情况是1的个数>0。sb题WA两发。。
HDU 6186 CS Course
#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<map>
#include<string>
using namespace std;
const int MAXN=100007;
int sum[35];
int a[MAXN];
int main()
{
int n, q;
while(scanf("%d%d", &n, &q)==2)
{
memset(sum, 0, sizeof(sum));
int xorval=0;
for(int i=1;i<=n;i++)
{
scanf("%d", &a[i]);
xorval^=a[i];
for(int j=0;j<30;j++)
{
if((1<<j)&a[i])
sum[j]++;
}
}
for(int i=1;i<=q;i++)
{
int kk;scanf("%d", &kk);
int andval=0, orval=0;
for(int j=0;j<30;j++)
{
if((1<<j)&a[kk])
{
if(sum[j]>1)
orval|=(1<<j);
if(sum[j]==n)
andval|=(1<<j);
}
else
{
if(sum[j]>0)
orval|=(1<<j);
if(sum[j]==n-1)
andval|=(1<<j);
}
}
printf("%d %d %d\n", andval, orval, xorval^a[kk]);
}
}
return 0;
}
老谭发现数学题后就一直在搞,D题,wa一发后过了。我完全没看。。。
HDU 6185 Covering
#include <cstdio>
#include <cstring>
#include <algorithm>
#define MAXN 6
#define LL long long
using namespace std;
const LL m=1000000007;
struct Matrix
{
LL a[MAXN][MAXN];
int r, c;
};
Matrix ori, res;
LL F[5];//F矩阵
LL Ans[5];//结果矩阵
void init()
{
//构造矩阵
ori.r = ori.c = 4;
memset(ori.a, 0, sizeof(ori.a));
ori.a[0][0] = ori.a[0][2] = 1;
ori.a[0][3] = -1;
ori.a[0][1] = 5;
ori.a[1][0] = ori.a[2][1] = ori.a[3][2] = 1;
//构造单位矩阵
res.r = res.c = 4;
memset(res.a, 0, sizeof(res.a));
res.a[0][0] = res.a[1][1] = res.a[2][2] = res.a[3][3] = 1;
//构造F矩阵
F[0] = 11, F[1] = 5, F[2] = 1, F[3] = 1;
}
Matrix muitl(Matrix x, Matrix y)
{
Matrix z;
memset(z.a, 0, sizeof(z.a));
z.r = x.r; z.c = y.c;
for(int i = 0; i < x.r; i++)
{
for(int k = 0; k < x.c; k++)
{
if(x.a[i][k] == 0) continue;
for(int j = 0; j < y.c; j++)
z.a[i][j] = (z.a[i][j] + (x.a[i][k] * y.a[k][j]) % m +m) % m;
}
}
return z;
}
void Matrix(LL n)
{
while(n)
{
if(n & 1)
res = muitl(ori, res);
ori = muitl(ori, ori);
n >>= 1;
}
}
void solve(LL n)
{
Matrix(n);//矩阵的n次幂 对m取余
memset(Ans, 0, sizeof(Ans));
for(int i = 0; i < res.r; i++)
{
for(int k = 0; k < res.c; k++)
Ans[i] = (Ans[i] + res.a[i][k] * F[k]%m +m ) % m;
}
printf("%lld\n", (Ans[0]+m)%m);
}
int main()
{
LL L;
while(scanf("%lld", &L) != EOF)
{
Ans[0] = 1, Ans[1] = 1, Ans[2] = 5, Ans[3] = 11;
if(L <= 3)
{
printf("%lld\n", Ans[L]);
continue;
}
init();//构造矩阵
solve(L-3);
}
return 0;
}
我做完E后就一直和学弟打扑克,疯狂贪心,不过一直没太好的策略,一开始想的复杂了,情况太多了。期间老谭又过了F题。
HDU 6187 Destroy Walls
#include <bits/stdc++.h>
using namespace std;
const int maxn=100007;
const int maxm=2000*1007;
struct Edge
{
int u,v,dist;
Edge(){}
Edge(int u,int v,int d):u(u),v(v),dist(d){}
bool operator<(const Edge &rhs)const
{
return dist >rhs.dist;//按边长从大到小排序
}
};
struct Kruskal
{
int n,m;
Edge edges[maxm];
int fa[maxn];
int findset(int x){return fa[x]==-1? x:fa[x]=findset(fa[x]); }
void init(int n)
{
this->n=n;
m=0;
memset(fa,-1,sizeof(fa));
}
void AddEdge(int u,int v,int dist)
{
edges[m++]=Edge(u,v,dist);
}
pair<int,int> kruskal()
{
pair<int,int> ans;
sort(edges,edges+m);
for(int i=0;i<m;i++)
{
int u=edges[i].u, v=edges[i].v;
if(findset(u) != findset(v))
{
fa[findset(u)] = findset(v);
ans.first++;
ans.second+=edges[i].dist;
}
}
return ans;
}
}KK;
int main() {
int n,m;
while(scanf("%d %d",&n,&m)!=EOF){
int u,v,w;
int sum=0;
KK.init(n);
for(int i=1;i<=n;i++)
scanf("%d %d",&u,&v);
for(int i=1;i<=m;i++)
scanf("%d %d %d",&u,&v,&w),
KK.AddEdge(u,v,w),
sum+=w;
pair<int,int>ans = KK.kruskal();
printf("%d %d\n",m-ans.first,sum-ans.second);
}
return 0;
}
G我们终于有了个比较简单的思路,当前牌i先全组对子,要是没剩的就继续下一张,要是剩一张就判断i+1的个数是不是奇数,要是是奇数就判断i+2有没有,有就组个顺子。正确性:假如i+1是偶数,那么不要拆对子,无论i+2奇偶都不会变坏;i+1奇数,就可以拿出多与的一张,这样即使i+2是偶数,也就是吧一个对子(i+2的)换成了顺子,也不会变坏。
HDU 6188 Duizi and Shunzi
#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<map>
#include<string>
using namespace std;
const int MAXN=100007;
int cd[MAXN];
int main()
{
int n;
while(scanf("%d", &n)==1)
{
int sum=0;
memset(cd, 0, sizeof(cd));
for(int i=1;i<=n;i++)
{
int tmp;scanf("%d", &tmp);
cd[tmp]++;
}
for(int i=1;i<MAXN-5;i++)
{
sum+=(cd[i]/2);
cd[i]%=2;
if(cd[i]>=1&&cd[i+1]%2==1&&cd[i+2]>=1)
{
sum++;
cd[i]--;
cd[i+1]--;
cd[i+2]--;
}
}
printf("%d\n", sum);
}
return 0;
}
这时已经过去2小时,可做题还有JBC(H?)。BJ是数据结构,C是个搜索计数,H不知道是什么。
我和学弟讨论一下J,异或可以用字典树处理,他觉得是可持久化字典树,不过不知道怎么写,我就打算写启发式合并。正打算写(感觉也写不出来),旁边队蓝名巨佬告诉我他打广西的网络同步赛用dsu过的,我瞬间兴奋,苦学一周的dsu不能浪费啊。直接上dsu+字典树。
这里说一嘴,dsu的复杂度和编码难度都比较不错,不过一般需要一种辅助数据结构去配合,就是看能不能想到这种辅助结构。解决树上无修改问题基本都能用。
HDU 6191 Query on A Tree
第一发T是因为没清vector,第二发re是因为字典树的节点个数n没清零。。。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<map>
#include<string>
#define M(a,b) memset(a,b,sizeof(a))
using namespace std;
const int MAXN=100007;
vector<int> G[MAXN];
int val[MAXN];
struct Query
{
int id;
int v;
int ne;
}q[MAXN];
int qhead[MAXN];
int qnum=0;
int res[MAXN];
const int bit=30;
struct Trie
{
int s;
int ch[2];
Trie() { s=ch[0]=ch[1]=0; }
}trie[MAXN*bit];
int sz=1;
void build() { M(trie, 0);sz=1; }
void insert(int rt, int lev, int num)
{
if(lev==-1) { trie[rt].s=1;return; }
int k=(num&(1<<lev))>>lev;
if(!trie[rt].ch[k]) trie[rt].ch[k]=++sz;
insert(trie[rt].ch[k], lev-1, num);
trie[rt].s=trie[trie[rt].ch[0]].s|trie[trie[rt].ch[1]].s;
}
void remove(int rt, int lev, int num)
{
if(lev==-1) { trie[rt].s=0;return; }
int k=(num&(1<<lev))>>lev;
remove(trie[rt].ch[k], lev-1, num);
trie[rt].s=trie[trie[rt].ch[0]].s|trie[trie[rt].ch[1]].s;
}
int query(int rt, int lev, int val)
{
if(lev==-1) return 0;
if((val&(1<<lev))>0)
{
if(trie[trie[rt].ch[0]].s==1)
{
return query(trie[rt].ch[0], lev-1, val);
}
else
{
return query(trie[rt].ch[1], lev-1, val)+(1<<lev);
}
}
else
{
if(trie[trie[rt].ch[1]].s==1)
{
return query(trie[rt].ch[1], lev-1, val)+(1<<lev);
}
else
{
return query(trie[rt].ch[0], lev-1, val);
}
}
}
int hson[MAXN], sonsz[MAXN];
void dfs1(int u, int fa)
{
sonsz[u]=1;
for(int i=0;i<G[u].size();i++)
{
if(G[u][i]!=fa)
{
dfs1(G[u][i], u);
if(hson[u]==-1)
{
hson[u]=G[u][i];
}
else if(sonsz[hson[u]]<sonsz[G[u][i]])
{
hson[u]=G[u][i];
}
sonsz[u]+=sonsz[G[u][i]];
}
}
}
int hs;
void add(int x)
{
insert(1, bit, val[x]);
for(int i=0;i<G[x].size();i++)
if(G[x][i]!=hs)
add(G[x][i]);
}
void del(int x)
{
remove(1, bit, val[x]);
for(int i=0;i<G[x].size();i++)
if(G[x][i]!=hs)
del(G[x][i]);
}
void dfs2(int u, int fa, int kp)
{
for(int i=0;i<G[u].size();i++)
if(G[u][i]!=hson[u])
{
dfs2(G[u][i], u, 0);
}
if(hson[u]) dfs2(hson[u], u, 1), hs=hson[u];
add(u);hs=0;
for(int i=qhead[u];~i;i=q[i].ne)
{
res[q[i].id]=query(1, bit, q[i].v);
res[q[i].id]^=q[i].v;
}
if(!kp)
del(u);
}
int main()
{
int n, qq;
while(scanf("%d%d", &n, &qq)==2)
{
for(int i=1;i<=n;i++)G[i].clear();
for(int i=1;i<=n;i++)
{
scanf("%d", &val[i]);
}
for(int i=2;i<=n;i++)
{
int k;scanf("%d", &k);
G[k].push_back(i);
}
memset(qhead, -1, sizeof(qhead));
qnum=0;
for(int i=1;i<=qq;i++)
{
int x, v;
scanf("%d%d", &x, &v);
q[++qnum].v=v;
q[qnum].ne=qhead[x];
qhead[x]=qnum;
q[qnum].id=i;
}
M(hson, 0);
build();
dfs1(1, 0);
dfs2(1, 0, 0);
for(int i=1;i<=qq;i++)
{
printf("%d\n", res[i]);
}
}
return 0;
}
我写J时学弟在搞数星星,不过赛后才搞出来。我写过J后就搞B的数据结构,二维的。不过处理一下可以变成一维的。先是C的代码:
HDU 6184 Counting Stars
#include<bits\stdc++.h>
using namespace std;
vector<int>G[100005];
set<long long>s;
int n, m, cnt, fa[100005];
bool vis[100005];
long long ans;
long long getint()
{
long long ret=0;
char ch=getchar();
while(ch<'0'||ch>'9')ch=getchar();
while('0'<=ch&&ch<='9') { ret=ret*10+ch-'0';ch=getchar(); }
return ret;
}
int main()
{
while(~scanf("%d%d", &n, &m))
{
memset(vis, 0, sizeof(vis));
memset(fa, 0, sizeof(fa));
s.clear();
for(int i=1;i<=n;i++)G[i].clear();
for(int i=1;i<=m;i++)
{
long long x=getint();
long long y=getint();
G[x].push_back(y);
s.insert((long long)n*x+y);
s.insert((long long)n*y+x);
G[y].push_back(x);
}
long long ans=0;
for(int i=1;i<=n;i++)
{
vis[i]=1;
int x=i;
for(int j=0;j<G[x].size();j++)fa[G[x][j]]=x;
for(int j=0;j<G[x].size();j++)
{
int y=G[x][j];
if(vis[y])continue;
long long sum=0;
if(G[y].size()<=(int)sqrt(m))
{
for(int k=0;k<G[y].size();k++)
{
int z=G[y][k];
if(fa[z]==x)sum++;
}
}
else
{
for(int k=0;k<G[x].size();k++)
{
int z=G[x][k];
if(s.find((long long)z*n+y)!=s.end())sum++;
}
}
ans+=(sum-1)*sum/2;
}
}
printf("%lld\n", ans);
}
return 0;
}