这是我们分组后Dots_lzl小组第一次参加组队赛,也是很开心的一次,虽然只A了2道题目(本来应该是三道的,已经AC了,但是却说时间到了,居然说是因为比赛提前开始了几分钟,我们就是在最后几分钟A的呀,别的组WA20多次,我们5次过的题目,他居然封榜了),以下仅有C,E,K是我们组做的
本题很简单,明显的2-SAT的模版题。
这题是2-SAT。只不过模板写错了一点,多加了个分号,导致样例一直出不来。幸好调试之后发现,
修改一下,交上去1A,爽~~~~此题是做得最顺利的了。
现场赛的时候内存真的是无穷大啊,直接做31*500*2=31000个点的2-SAT就AC了。但是比赛结束后在ZOJ上就会MLE了~~~~~
要分开做,做31次的2-SAT就可以了~~~~~~
#include<stdio.h> #include<iostream> #include<algorithm> #include<vector> #include<queue> #include<string.h> using namespace std; const int MAXN=1100;// bool visit[MAXN]; queue<int>q1,q2; //vector建图方法很妙 vector<vector<int> >adj; //原图 //中间一定要加空格把两个'>'隔开 vector<vector<int> >radj;//逆图 vector<vector<int> >dag;//缩点后的逆向DAG图 int n,m,cnt; int id[MAXN],order[MAXN],ind[MAXN];//强连通分量,访问顺序,入度 void dfs(int u) { visit[u]=true; int i,len=adj[u].size(); for(i=0;i<len;i++) if(!visit[adj[u][i]]) dfs(adj[u][i]); order[cnt++]=u; } void rdfs(int u) { visit[u]=true; id[u]=cnt; int i,len=radj[u].size(); for(i=0;i<len;i++) if(!visit[radj[u][i]]) rdfs(radj[u][i]); } void korasaju() { int i; memset(visit,false,sizeof(visit)); for(cnt=0,i=0;i<2*n;i++) if(!visit[i]) dfs(i); memset(id,0,sizeof(id)); memset(visit,false,sizeof(visit)); for(cnt=0,i=2*n-1;i>=0;i--) if(!visit[order[i]]) { cnt++;//这个一定要放前面来 rdfs(order[i]); } } bool solvable() { for(int i=0;i<n;i++) if(id[2*i]==id[2*i+1]) return false; return true; } void add(int x,int y) { adj[x].push_back(y); radj[y].push_back(x); } int b[600][600]; int bit[33]; int main() { int N; bit[0]=1; for(int i=1;i<31;i++)bit[i]=2*bit[i-1]; while(scanf("%d",&N)!=EOF) { n=N; bool flag=true; for(int i=0;i<N;i++) for(int j=0;j<N;j++) { scanf("%d",&b[i][j]); if(i==j&&b[i][j]!=0)flag=false; } if(!flag) { printf("NO\n"); continue; } for(int i=0;i<N;i++) { if(!flag)break; for(int j=i+1;j<N;j++) if(b[i][j]!=b[j][i]) { flag=false; break; } } if(!flag) { printf("NO\n"); continue; } for(int k=0;k<31;k++) { adj.assign(2*n,vector<int>()); radj.assign(2*n,vector<int>()); for(int i=0;i<N;i++) for(int j=i+1;j<N;j++) { if(i%2==1&&j%2==1) { int t1=i; int t2=j; if(b[i][j]&bit[k]) { add(2*t1,2*t2+1); add(2*t2,2*t1+1); } else { add(2*t1+1,2*t1); add(2*t2+1,2*t2); } } else if(i%2==0&&j%2==0) { int t1=i; int t2=j; if(b[i][j]&bit[k]) { add(2*t1,2*t1+1); add(2*t2,2*t2+1); } else { add(2*t1+1,2*t2); add(2*t2+1,2*t1); } } else { int t1=i; int t2=j; if(b[i][j]&bit[k]) { add(2*t1,2*t2+1); add(2*t1+1,2*t2); add(2*t2,2*t1+1); add(2*t2+1,2*t1); } else { add(2*t1,2*t2); add(2*t1+1,2*t2+1); add(2*t2,2*t1); add(2*t2+1,2*t1+1); } } } korasaju(); if(!solvable()) { flag=false; break; } } if(flag)printf("YES\n"); else printf("NO\n"); } return 0; }
C -The Little Girl who Picks Mushrooms
#include<stdio.h>
#include<string.h>
#define max(a , b) (a)>(b)?(a):(b)
int main()
{
int a[5] , d[10][5]={0,1,2,3,4,0,1,3,2,4,0,1,4,2,3,0,2,3,1,4,0,2,4,1,3,0,3,4,1,2,1,2,3,0,4,1,2,4,0,3,1,3,4,0,2,2,3,4,0,1};
int n , M , i , j , temp ,flag;
while(scanf("%d",&n)!=EOF)
{
M=0;
memset(a , -1 , sizeof(a));
for(i=0 ; i<n ; i++)
scanf("%d",&a[i]);
for(i=0;i<10;i++)
{
temp=flag=0;
for(j=0 ; j<3 ; j++)
if(a[d[i][j]]==-1)
{
flag=1;
break;
}
else
temp += a[d[i][j]];
j=3;
if(flag)
{
temp=0;
for(j ; j<5 ; j++)
if(a[d[i][j]]==-1)
{
M=1024;
break;
}
else
{
temp += a[d[i][j]];
}
if(M==1024)
break;
while(temp>1024)
temp -= 1024;
M=max(M,temp);
}
else
{
if(temp%1024==0)
{
temp=0;
for(j ; j<5 ; j++)
if(a[d[i][j]]==-1)
{
M=1024;
break;
}
else
temp += a[d[i][j]];
if(M==1024)
break;
while(temp>1024)
temp -= 1024;
M=max(M , temp);
}
}
}
printf("%d\n" , M);
}
return 0;
}
#include<stdio.h>//这个是转的
#include<string.h>
#include<algorithm>
#include<iostream>
using namespace std;
int a[6];
int main()
{
int n;
while(scanf("%d",&n)!=EOF)
{
int sum=0;
for(int i=0;i<n;i++)
{
scanf("%d",&a[i]);
sum+=a[i];
}
if(n>=0&&n<=3)
{
printf("1024\n");
continue;
}
int ans=0;
if(n==5)
{
for(int i=0;i<5;i++)
for(int j=i+1;j<5;j++)
for(int k=j+1;k<5;k++)
if((a[i]+a[j]+a[k])%1024==0)
{
int temp=sum-a[i]-a[j]-a[k];
while(temp>1024)temp-=1024;
if(temp>ans)ans=temp;
}
printf("%d\n",ans);
continue;
}
if(n==4)
{
ans=0;
for(int i=0;i<4;i++)
for(int j=i+1;j<4;j++)
for(int k=j+1;k<4;k++)
if((a[i]+a[j]+a[k])%1024==0)
{
ans=1024;
}
if(ans>0)
{
printf("1024\n");
continue;
}
for(int i=0;i<4;i++)
for(int j=i+1;j<4;j++)
{
int temp=a[i]+a[j];
while(temp>1024)temp-=1024;
if(temp>ans)ans=temp;
}
printf("%d\n",ans);
continue;
}
}
return 0;
}
E -Conquer a New Region
# include<cstdio>
# include<cstring>
# include<algorithm>
const int maxn=200001;
using namespace std;
struct Edge
{
int u,v,w;
}edge[maxn];
int f[maxn],num[maxn];
long long cost[maxn];
int find(int x)
{
/*if(f[u]==u) return u;
return f[u] = find(f[u]);*/
return x==f[x]?x:find(f[x]);
}
bool cmp(struct Edge a,struct Edge b)
{
return a.w > b.w;
}
int main()
{
int n,i;
while(scanf("%d",&n)!=EOF)
{
for(i=1;i<n;i++)
scanf("%d%d%d",&edge[i].u,&edge[i].v,&edge[i].w);
sort(edge+1,edge+n,cmp);
for(i=1;i<=n;i++)
f[i] = i, num[i]=1, cost[i]=0;
for(i=1;i<n;i++)
{
int x1=find(edge[i].u);
int x2=find(edge[i].v);
if(x1!=x2)
{
cost[x2] = max((long long)num[x1]*edge[i].w+cost[x2],(long long)num[x2]*edge[i].w+cost[x1]);
num[x2]+=num[x1];
f[x1]=x2;
}
}
printf("%lld\n",cost[find(1)]);
}
return 0;
}
很水的DP,长春赛的时候竟然没有做出来。。。。。方向是写对了的,只是最后半个小时写的,很紧张。最后超时了。
需要注意些细节,一些初始化才不会超时。
预处理出LCM[1000][1000]来。
dp[now][i][j]表示当前状态下,和为i,LCM为j的解的个数。递推K次就出答案了#include<stdio.h>
#include<algorithm>
#include<string.h>
#include<iostream>
using namespace std;
const int MOD=1000000007;
int dp[2][1010][1010];
int num[1000];
int gcd(int a,int b)
{
if(b==0)return a;
return gcd(b,a%b);
}
int lcm(int a,int b)
{
return a/gcd(a,b)*b;
}
int LCM[1010][1010];
int main()
{
int n,m,k;
for(int i=1;i<=1000;i++)
for(int j=1;j<=1000;j++)
LCM[i][j]=lcm(i,j);
while(scanf("%d%d%d",&n,&m,&k)!=EOF)
{
int cnt=0;
for(int i=1;i<=m;i++)
{
if(m%i==0)
num[cnt++]=i;
}
int now=0;
//memset(dp[now],0,sizeof(dp[now]));
for(int i=0;i<=n;i++)
for(int j=0;j<cnt;j++)
dp[now][i][num[j]]=0;
dp[now][0][1]=1;
for(int t=1;t<=k;t++)
{
now^=1;
// memset(dp[now],0,sizeof(dp[now]));
for(int i=0;i<=n;i++)
for(int j=0;j<cnt;j++)
dp[now][i][num[j]]=0;
for(int i=t-1;i<=n;i++)
for(int j=0;j<cnt;j++)
{
if(dp[now^1][i][num[j]]==0)continue;
for(int p=0;p<cnt;p++)
{
int x=i+num[p];
//int y=lcm(num[j],num[p]);
int y=LCM[num[j]][num[p]];
if(x>n||m%y!=0)continue;
dp[now][x][y]+=dp[now^1][i][num[j]];
dp[now][x][y]%=MOD;
}
}
}
printf("%d\n",dp[now][n][m]);
}
return 0;
}
J -Split the Rectangle
其实这题是不难的,注意是看懂题目意思。
只要按照加入的边建立树。
然后每次的查询就是求出这个点所在的叶子结点编号。然后求出这两个叶子结点的LCA,暴力求LCA即可。
然后答案就是 n+1-(LCA所在结点下面的叶子结点个数)+1
很好的一道题。
注意给的点是没有顺序的。
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<iostream>
#include<math.h>
using namespace std;
const int MAXN=2020;
struct Node
{
int lson,rson,father;
int dep;//深度
int xl,yl,xr,yr;
void init(int de,int f)
{
lson=rson=0;
father=f;
dep=de;
}
void update(int a,int b,int c,int d)
{
xl=a;yl=b;xr=c;yr=d;
}
}node[MAXN];//结点
int tol;
int num[MAXN];//每个结点下的叶子结点个数
int root;//根结点
int find(int root,int x,int y)
{
int tmp=root,tt;
while(1)
{
if(node[tmp].lson==0)return tmp;
tt=node[tmp].lson;
if(x<=node[tt].xr&&x>=node[tt].xl&&y>=node[tt].yl&&y<=node[tt].yr)tmp=tt;
else tmp=node[tmp].rson;
}
}
int get_num(int now)
{
num[now]=0;
if(node[now].lson==0)
{
return num[now]=1;
}
else
{
num[now]+=get_num(node[now].lson);
num[now]+=get_num(node[now].rson);
}
return num[now];
}
int main()
{
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
int xl,yl,xr,yr;
int n,q;
while(scanf("%d%d%d%d",&xl,&yl,&xr,&yr)!=EOF)
{
root=0;
node[root].init(0,-1);
node[root].update(xl,yl,xr,yr);
tol=1;
scanf("%d%d",&n,&q);
for(int i=1;i<=n;i++)
{
scanf("%d%d%d%d",&xl,&yl,&xr,&yr);
if(xl>xr)swap(xl,xr);
if(yl>yr)swap(yl,yr);
int pos=find(root,(xl+xr)/2,(yl+yr)/2);
int dep=node[pos].dep;
node[pos].lson=tol;
node[tol].init(dep+1,pos);
node[tol].update(node[pos].xl,node[pos].yl,xr,yr);
tol++;
node[pos].rson=tol;
node[tol].init(dep+1,pos);
node[tol].update(xl,yl,node[pos].xr,node[pos].yr);
tol++;
}
get_num(root);
while(q--)
{
scanf("%d%d%d%d",&xl,&yl,&xr,&yr);
int tmp1=find(root,xl,yl);
int tmp2=find(root,xr,yr);
while(tmp1!=tmp2)
{
if(node[tmp1].dep<node[tmp2].dep)tmp2=node[tmp2].father;
else if(node[tmp1].dep>node[tmp2].dep)tmp1=node[tmp1].father;
else
{
tmp1=node[tmp1].father;
tmp2=node[tmp2].father;
}
}
printf("%d\n",n+1-num[tmp1]+1);
}
}
return 0;
}
K -Yukari's Birthday
// File Name: eee.cpp
// Author: rudolf
// Created Time: 2013年04月17日 星期三 19时16分37秒
#include<math.h>
#include<stdio.h>
#define LL long long
LL Pow(int x ,int y)
{
int i;
LL sum=1;
for(i=0;i<y;i++ )
sum *= x ;
return sum ;
}
int main()
{
LL n,le,ri,k,mid,ans;
LL i , j,r;
while(scanf("%lld",&n)!= EOF)
{
r=1;
k=n-1;
for(i=2;i<=46;i++)
{
le = 2 ;
ri = pow(n,1.0/i);
while(le<=ri)
{
mid=(LL)(le+ri)/2;
ans = (mid-Pow(mid,i+1))/(1-mid);
if(ans==n|| ans==(n - 1))
{
if(r*k>i*mid)
{
r=i;
k=mid;
}
break;
}
else if(ans > n)
ri = mid - 1;
else
le = mid + 1;
}
}
printf("%lld %lld\n",r,k);
}
return 0;
}