2014多校联合训练第⑨场

算是今年多校比较友好的一场比赛了

1002

http://acm.hdu.edu.cn/showproblem.php?pid=4961

解题思路:题意看上去比较绕,实际上就是求对于每个a[i]其左右两边最靠近它的且是它的倍数的数各是多少,首先不难想到预处理出1-1e5的数的约数,然后我们从左到右扫一遍每次更新当前数字的所有约数的所求位置,同时当前位置的b[i]也就确定下来了,同理从右向左扫一遍处理出c[i]数组,然后相乘求和即可。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>
#include <set>
#include <map>
#include <list>
#include <queue>
#include <stack>
#include <deque>
#include <vector>
#include <bitset>
#include <cmath>
#include <utility>
#define Maxn 100005
#define Inf 0x3f3f3f3f
#define lowbit(x) x&(-x)
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define PI acos(-1.0)
#define LL long long
#define make_pair MP 
#define re freopen("in.txt","r",stdin)
#define wr freopen("out.txt","w",stdout)
using namespace std;
LL a[Maxn],b[Maxn],c[Maxn];
int pos[Maxn];
vector<int> yueshu[Maxn+5];
void get_yueshu()
{
	for(int i=0;i<Maxn;i++)
		yueshu[i].clear();
	for(int i=1;i<Maxn;i++)
		for(int j=i;j<Maxn;j+=i)
			yueshu[j].push_back(i);
}
void solve(int n)
{
	LL ans=0;
	memset(pos,0,sizeof(pos));
	for(int i=1;i<=n;i++)
	{
		int u=a[i];
		int k=pos[u]==0?i:pos[u];
		b[i]=a[k];
		int s=yueshu[u].size();
		for(int j=0;j<s;j++)
			pos[yueshu[u][j]]=max(pos[yueshu[u][j]],i);
	}
	memset(pos,Inf,sizeof(pos));
	for(int i=n;i>=1;i--)
	{
		int u=a[i];
		int k=pos[u]==Inf?i:pos[u];
		c[i]=a[k];
		int s=yueshu[u].size();
		for(int j=0;j<s;j++)
			pos[yueshu[u][j]]=min(pos[yueshu[u][j]],i);
	}
	for(int i=1;i<=n;i++)
		ans+=b[i]*c[i];
	printf("%I64d\n",ans);
}
int main()
{
	int n;
	//re;
	//wr;
	get_yueshu();
	while(~scanf("%d",&n),n)
	{
		for(int i=1;i<=n;i++)
			scanf("%I64d",a+i);
		solve(n);
	}
	return 0;
}

1006

http://acm.hdu.edu.cn/showproblem.php?pid=4965

解题思路:矩阵快速幂,但是不能直接求,C=A*B,C^(N*N))就是(A*B)^(N*N)即A*B*A*B...*A*B因为矩阵乘法满足结合律而B*A最大是一个6*6的矩阵那么就是A*(B*A)^(N*N-1)*B,中间部分矩阵快速幂即可

#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>
#include <set>
#include <map>
#include <list>
#include <queue>
#include <stack>
#include <deque>
#include <vector>
#include <bitset>
#include <cmath>
#include <utility>
#define Maxn 1005
#define Inf 0x3f3f3f3f
#define lowbit(x) x&(-x)
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define PI acos(-1.0)
#define make_pair MP
#define LL long long 
#define re freopen("in.txt","r",stdin)
#define wr freopen("out.txt","w",stdout)
using namespace std;
struct Matrix
{
    int val[7][7];
    int m,n;
    Matrix()
    {
    	m=n=0;
    	memset(val,0,sizeof(val));
    }
    friend Matrix operator *(Matrix &A,Matrix &B)
    {
        Matrix tmp;
        for(int i=1;i<=A.m;i++)
            for(int j=1;j<=B.n;j++)
                for(int k=1;k<=A.n;k++)
                {
                    tmp.val[i][j]+=A.val[i][k]*B.val[k][j];
                    tmp.val[i][j]%=6;
                }
        tmp.m=A.m;tmp.n=B.n;
        return tmp;
    }
    friend Matrix operator ^(Matrix &x,int n)
    {
        Matrix tmp;
        tmp.m=x.m;tmp.n=x.n;
        for(int i=1;i<=x.m;i++)
            tmp.val[i][i]=1;
        while(n)
        {
            if(n&1)
                tmp=tmp*x;
            x=x*x;
            n>>=1;
        }
        return tmp;
    }
};
int mp1[Maxn][7],mp2[7][Maxn],mp3[Maxn][7],mp4[Maxn][Maxn];
int i,j,k,N,K,ans;
void mul1(Matrix &C)
{
	for(int i=1;i<=K;i++)
        for(int j=1;j<=K;j++)
        {
        	for(int k=1;k<=N;k++)
        	{
        		C.val[i][j]+=mp2[i][k]*mp1[k][j];
        		C.val[i][j]%=6;
        	}
        }
}
void mul2(Matrix C)
{
	for(int i=1;i<=N;i++)
		for(int j=1;j<=K;j++)
			for(int k=1;k<=K;k++)
			{
				mp3[i][j]+=mp1[i][k]*C.val[k][j];
				mp3[i][j]%=6;
			}
}
void mul3()
{
	for(int i=1;i<=N;i++)
		for(int j=1;j<=N;j++)
			for(int k=1;k<=K;k++)
			{
				mp4[i][j]+=mp3[i][k]*mp2[k][j];
				mp4[i][j]%=6;
			}
}
int main()
{
    //re;
    //wr;
    while(~scanf("%d%d",&N,&K),N+K)
    {
    	Matrix C;
        ans=0;
        memset(mp1,0,sizeof(mp1));
        memset(mp2,0,sizeof(mp2));
        memset(mp3,0,sizeof(mp3));
        memset(mp4,0,sizeof(mp4));
        for(i=1;i<=N;i++)
            for(j=1;j<=K;j++)
           	    scanf("%d",&mp1[i][j]);
        for(i=1;i<=K;i++)
            for(j=1;j<=N;j++)
	            scanf("%d",&mp2[i][j]);
        mul1(C);
        C.m=C.n=K;
        C=C^(N*N-1);
        mul2(C);
        mul3();
        for(i=1;i<=N;i++)
            for(j=1;j<=N;j++)
                ans+=mp4[i][j]%6;
        printf("%d\n",ans);
    }
    return 0;
}

1007

http://acm.hdu.edu.cn/showproblem.php?pid=4966

解题思路:最小树形图模板题,将a课程的b等级与c课程的d等级连一条权值为w的边,同时同一课程的高等级向低等级连一条权值为0的边,所有课程的1等级向0号点连一条权值为0的边,跑一下最小树形图的模板即可

#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>
#include <set>
#include <map>
#include <list>
#include <queue>
#include <stack>
#include <deque>
#include <vector>
#include <bitset>
#include <cmath>
#include <utility>
#define Maxn 505
#define Maxm 10005
#define Inf 0x3f3f3f3f
#define lowbit(x) x&(-x)
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define PI acos(-1.0)
#define make_pair MP
#define LL long long 
#define re freopen("in.txt","r",stdin)
#define wr freopen("out.txt","w",stdout)
using namespace std;
struct Edge
{
	int s,e,w;
};
Edge edge[Maxm];
int pre[Maxm],vis[Maxm],id[Maxm],in[Maxm],L;
void add(int s,int e,int w)
{
	edge[L].s=s;
	edge[L].e=e;
	edge[L++].w=w;
}
int zhuliu(int root,int n,int m,Edge edge[])
{
	int res=0,s,e;
	while(1)
	{
		for(int i=0;i<n;i++)
			in[i]=Inf;
		for(int i=0;i<m;i++)
			if(edge[i].s!=edge[i].e&&edge[i].w<in[edge[i].e])
			{
				pre[edge[i].e]=edge[i].s;
				in[edge[i].e]=edge[i].w;
			}
		for(int i=0;i<n;i++)
			if(i!=root&&in[i]==Inf)
				return -1;
		int tn=0;
		memset(id,-1,sizeof(id));
		memset(vis,-1,sizeof(vis));
		in[root]=0;
		for(int i=0;i<n;i++)
		{
			res+=in[i];
			e=i;
			while(vis[e]!=i&&id[e]==-1&&e!=root)
			{
				vis[e]=i;
				e=pre[e];
			}
			if(e!=root&&id[e]==-1)
			{
				for(s=pre[e];s!=e;s=pre[s])
					id[s]=tn;
				id[e]=tn++;
			}
		}
		if(tn==0)
			break;
		for(int i=0;i<n;i++)
			if(id[i]==-1)
				id[i]=tn++;
		for(int i=0;i<m;i++)
		{
			e=edge[i].e;
			edge[i].s=id[edge[i].s];
			edge[i].e=id[edge[i].e];
			if(edge[i].s!=edge[i].e)
				edge[i].w-=in[e];
		}
		n=tn;
		root=id[root];
	}
	return res;
}
int main()
{
	int m,n,a[55],c,d,l1,l2,w,N;
	//re;wr;
	while(~scanf("%d%d",&n,&m),m+n)
	{
		N=L=0;
		memset(a,0,sizeof(a));
		for(int i=1;i<=n;i++)
		{
			add(a[i-1]+1,0,0);
			scanf("%d",a+i);
			for(int j=2;j<=a[i];j++)
				add(a[i-1]+j,a[i-1]+j-1,0);
			a[i]+=a[i-1];
		}
		N=a[n]+1;
		while(m--)
		{
			scanf("%d%d%d%d%d",&c,&l1,&d,&l2,&w);
			int s=l1==0?0:a[c-1]+l1;int e=l2==0?0:a[d-1]+l2;
			add(s,e,w);
		}
		printf("%d\n",zhuliu(0,N,L,edge));
	}
	return 0;
}

1008

http://acm.hdu.edu.cn/showproblem.php?pid=4967

解题思路:

给定一些入栈,出栈,弹出栈顶元素的操作和他们的时间戳,每次询问已经输入过的操作中时间戳在询问之前的最近的那个应该被弹出的元素是什么,我们把入栈操作当做在其时间戳位置+1,出栈操作当做在其时间戳位置-1,问题转化为求最小的i,使得sum[x]-sum[i-1]>0,x是询问时间戳位置。我们用线段树维护两个值区间和以及区间最大后缀的值,每次先向右子树查找,如果该区间的最大后缀值加上sigma(tree[i],R+1,x)大于0就说明在这个区间内,否则向左子树查找

#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>
#include <set>
#include <map>
#include <list>
#include <queue>
#include <stack>
#include <deque>
#include <vector>
#include <bitset>
#include <cmath>
#include <utility>
#define Maxn 50005
#define Maxm 10005
#define Inf 0x3f3f3f3f
#define lowbit(x) x&(-x)
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define ls rt<<1
#define rs rt<<1|1
#define PI acos(-1.0)
#define make_pair MP
#define LL long long 
#define re freopen("in.txt","r",stdin)
#define wr freopen("out.txt","w",stdout)
using namespace std;
int sum[Maxn<<2],rmax[Maxn<<2];
int ans;
struct Node
{
    int x,t,id;
    char op[10];
    Node()
    {
        x=t=id=0;
        memset(op,'\0',sizeof(op));
    }
};
bool cmp1(Node a,Node b)
{
    return a.t<b.t;
}
bool cmp2(Node a,Node b)
{
    return a.id<b.id;
}
Node cmd[Maxn];
void init(int n)
{
    for(int i=0;i<n;i++)
    {
        cmd[i].x=cmd[i].t=cmd[i].id=0;
        memset(cmd[i].op,'\0',sizeof(cmd[i].op));
    }
    memset(sum,0,sizeof(sum));
    memset(rmax,-Inf,sizeof(rmax));
}
int read()
{
    int res=0;
    while(1)
    {
         char ch=getchar();
         if(ch>='0'&&ch<='9')
             res=res*10+ch-'0';
         else
             break;
    }
    return res;
}
void push_up(int rt)
{
    sum[rt]=sum[ls]+sum[rs];
    rmax[rt]=max(rmax[rs],sum[rs]+rmax[ls]);
}
void update(int pos,int x,int l,int r,int rt)
{
    if(l==r)
    {
        sum[rt]=rmax[rt]=x;
        return ;
    }
    int m=(l+r)>>1;
    if(pos<=m)
        update(pos,x,lson);
    else
        update(pos,x,rson);
    push_up(rt);
}
int get_pos(int l,int r,int rt,int k)
{
    if(l==r)
        return l;
    int m=(l+r)>>1;
    if(k+rmax[rs]>0)
        return get_pos(rson,k);
    else
        return get_pos(lson,k+sum[rs]);
}
void query(int L,int R,int &k,int l,int r,int rt)
{
    if(ans)
        return ;
    if(L<=l&&R>=r)
    {
        if(rmax[rt]+k<=0)//k值用来维护sigma(sum[i],r+1,R)
            k+=sum[rt];
        else
            ans=get_pos(l,r,rt,k);
        return ;
    }
    int m=(l+r)>>1;
    if(R>m)
        query(L,R,k,rson);
    if(L<=m)
        query(L,R,k,lson);
    return ;
}
int main()
{
    int ncase=1;
    int n,id[Maxn];
    //re;wr;
    while(~scanf("%d",&n),n)
    {
        init(n);
        memset(id,0,sizeof(id));
        for(int i=0;i<n;i++)
        {
            scanf("%s",cmd[i].op);
            int len=strlen(cmd[i].op);
            cmd[i].op[len]='\0';
            getchar();
            if(cmd[i].op[1]=='u')
                cmd[i].x=read(),cmd[i].t=read();
            else if(cmd[i].op[1]=='o')
                cmd[i].t=read();
            else
                cmd[i].t=read();
            cmd[i].id=i;
        }
        sort(cmd,cmd+n,cmp1);
        for(int i=0;i<n;i++)
            cmd[i].t=i+1,id[cmd[i].t]=cmd[i].id;
        sort(cmd,cmd+n,cmp2);
        printf("Case #%d:\n",ncase++);
        for(int i=0;i<n;i++)
        {
            if(cmd[i].op[1]=='u')
                update(cmd[i].t,1,1,n,1);
            else if(cmd[i].op[1]=='o')
                update(cmd[i].t,-1,1,n,1);
            else
            {
                ans=0;
                int k=0;
                query(1,cmd[i].t,k,1,n,1);
                printf("%d\n",ans?cmd[id[ans]].x:-1);
            }
        }
    }
    return 0;
}


1009

解题思路:贪心即可,要高GPA就是让尽量多的科目处于恰好能拿到高绩点的最低分数,要低GPA就是让尽可能多的科目处在低绩点的最高分数上

#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>
#include <set>
#include <map>
#include <list>
#include <queue>
#include <stack>
#include <deque>
#include <vector>
#include <bitset>
#include <cmath>
#include <utility>
#define Maxn 1000005
#define Inf 0x3f3f3f3f
#define lowbit(x) x&(-x)
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define LL long long
#define make_pair MP 
#define PI acos(-1.0)
#define re freopen("in.txt","r",stdin)
#define wr freopen("out.txt","w",stdout)
using namespace std;
int l[]={60,70,75,80,85};
int r[]={69,74,79,84,100};
double gpa[]={2.0,2.5,3.0,3.5,4.0};
int main()
{
	int m,n,t,sum,now,ans1[5],ans2[5];
	double a,b;
	re;
	wr;
	scanf("%d",&t);
	while(t--)
	{
		a=b=0.0;
		memset(ans1,0,sizeof(ans1));
		memset(ans2,0,sizeof(ans2));
		scanf("%d%d",&n,&m);
		sum=m*n;
		now=m;
		for(int i=0;i<5;i++)
		{
			int k=now;
			while(k)
			{
				int tmp=k*r[i];
				if((now-k)*100<sum-tmp)
					k--;
				else
				{
					ans1[i]=k;
					break;
				}
			}
			sum-=k*r[i];
			now-=k;
		}
		sum=m*n;
		now=m;
		for(int i=4;i>=0;i--)
		{
			int k=now;
			while(k)
			{
				int tmp=k*l[i];
				if((now-k)*60>sum-tmp)
					k--;
				else
				{
					ans2[i]=k;
					break;
				}
			}
			sum-=k*l[i];
			now-=k;
		}
		for(int i=0;i<5;i++)
			a+=ans1[i]*gpa[i],b+=ans2[i]*gpa[i];
		a/=m;
		b/=m;
		printf("%.4lf %.4lf\n",a,b);
	}
	return 0;
}

1010

http://acm.hdu.edu.cn/showproblem.php?pid=4969

解题思路:数学积分,汉纸和妹纸要处在同一条直线上就是两人的角速度要时刻相同,令vx表示汉纸的切向速度,vy表示汉纸的径向速度,则vx/r=v1/R,v1^2=vx^2+vy^2,vy=sqrt(v1^2-(v2*r/R)^2)=dr/dt,令t0表示汉纸跑的时间积分得t0=R/v1*arcsin(v1/v2),判断下t0时间内能跑的距离是否大于d即可

#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>
#include <set>
#include <map>
#include <list>
#include <queue>
#include <stack>
#include <deque>
#include <vector>
#include <bitset>
#include <cmath>
#include <utility>
#define Maxn 50005
#define Maxm 10005
#define Inf 0x3f3f3f3f
#define lowbit(x) x&(-x)
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define ls rt<<1
#define rs rt<<1|1
#define PI acos(-1.0)
#define make_pair MP
#define LL long long 
#define re freopen("in.txt","r",stdin)
#define wr freopen("out.txt","w",stdout)
using namespace std;
int main()
{
	int T;
	scanf("%d",&T);
	double v1,v2,R,D;
	while(T--)
	{
        scanf("%lf%lf%lf%lf",&v1,&v2,&R,&D);
        double ans=R/v1*(asin(v1/v2));
        if(ans*v2>D)
            printf("Why give up treatment\n");
        else
            printf("Wake up to code\n");
	}
	return 0;
}

1011

http://acm.hdu.edu.cn/showproblem.php?pid=4970

解题思路:我是直接上线段树的,求怪物到终点的伤害是否大于h即可

#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>
#include <set>
#include <map>
#include <list>
#include <queue>
#include <stack>
#include <deque>
#include <vector>
#include <bitset>
#include <cmath>
#include <utility>
#define Maxn 100005
#define Inf 0x3f3f3f3f
#define lowbit(x) x&(-x)
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define PI acos(-1.0)
#define make_pair MP
#define LL long long 
#define re freopen("in.txt","r",stdin)
#define wr freopen("out.txt","w",stdout)
using namespace std;
LL tree[Maxn<<2];
int cover[Maxn<<2];
void push_up(int rt)
{
	tree[rt]=tree[rt<<1]+tree[rt<<1|1];
}
void push_down(int rt,int m)
{
	if(cover[rt])
	{
		cover[rt<<1]+=cover[rt];
		cover[rt<<1|1]+=cover[rt];
		tree[rt<<1]+=(m-(m>>1))*cover[rt];
		tree[rt<<1|1]+=(m>>1)*cover[rt];
		cover[rt]=0;
	}
}
void update(int L,int R,int x,int l,int r,int rt)
{
	if(L<=l&&R>=r)
	{
		tree[rt]+=x*(r-l+1);
		cover[rt]+=x;
		return ;
	}
	push_down(rt,r-l+1);
	int m=(l+r)>>1;
	if(L<=m)
		update(L,R,x,lson);
	if(R>m)
		update(L,R,x,rson);
	push_up(rt);
}
LL query(int L,int R,int l,int r,int rt)
{
	if(L<=l&&R>=r)
		return tree[rt];
	push_down(rt,r-l+1);
	int m=(l+r)>>1;
	LL ans=0;
	if(L<=m)
		ans+=query(L,R,lson);
	if(R>m)
		ans+=query(L,R,rson);
	return ans;
}
int main()
{
	int n,m,l,r,d,k,x,ans;
	LL h;
	//re;
	//wr;
	while(~scanf("%d",&n)&&n)
	{
		ans=0;
		memset(tree,0,sizeof(tree));
		memset(cover,0,sizeof(cover));
		scanf("%d",&m);
		while(m--)
		{
			scanf("%d%d%d",&l,&r,&d);
			update(l,r,d,1,n,1);
		}
		scanf("%d",&k);
		while(k--)
		{
			scanf("%I64d%d",&h,&x);
			ans+=query(x,n,1,n,1)<h?1:0;
		}
		printf("%d\n",ans);
	}
	return 0;
}


其实模仿树状数组区间修改的做法,用一个数组记录下后缀和更快

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std ; 

typedef __int64 ll ;

ll ak[100005],sum[100005] ;

int main()
{
    int n ;
    while(~scanf("%d",&n),n)
    {
        int m,k ;
        scanf("%d",&m) ;
        memset(ak,0,sizeof(ak)) ;
        memset(sum,0,sizeof(sum)) ;
        while(m--)
        {
            int L,R,D ;
            scanf("%d%d%d",&L,&R,&D) ;
            ak[L]+=(ll)D ;
            ak[R+1]-=(ll)D ;
        }
        for(int i=1 ;i<=n ;i++)
            sum[i]=sum[i-1]+ak[i] ;
        for(int i=n-1 ;i>0 ;i--)
            sum[i]+=sum[i+1] ;
        scanf("%d",&k) ;
        int ans=0 ;
        while(k--)
        {
            int x ;
            ll h ;
            scanf("%I64d%d",&h,&x) ;
            if(sum[x]<h)ans++ ;
        }
        printf("%d\n",ans) ;
    }
    return 0 ;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值