151224总结

151223

TJOI2015D1

 

T1 有意义的字符串

151224总结_第1张图片

然后就可以矩阵快速幂求出an+1啦~

注意,    1.n=0时要特判,就是在这儿丢了5分。。。

2.模数非常大,必须开unsigned long long ,然后写快速乘

 

复杂度:O(23logNlogx)

 

需要的知识:二阶递推、矩阵乘法

 

T2 城池攻占

可并堆,从叶子往根合并,当堆顶值不满足时就弹出,每个点只加入一次、弹出一次。在树上每个节点改变值的时候,像双标记线段树一样,打lazy标记。

卡常。。。

 

复杂度 O(NlogN)

 

需要的知识:可并堆

 

T3 装备购买

 151224总结_第2张图片

复杂度:O(N3)

 

需要的知识:贪心、高斯消元


T1

#include<iostream>
#include<algorithm>
#include<cstdlib>
#include<cstdio>
#include<string>
#include<cstring>
#include<ctime>
#include<cmath>
#define LL long long
#define ul unsigned long long
using namespace std;

const ul M = 7528443412579576937;
LL b,d,n,x,y;
ul ret[2][2],a[2][2],t[2][2];

ul ksc(ul a,ul b)
{
	ul ret=0;
	for (;b;b>>=1,a=(a<<1)%M)
		if (b&1) ret=(ret+a)%M;
	return ret;
}

void mul(ul a[][2],ul b[][2])
{
	for (int i=0;i<2;i++)
		for (int j=0;j<2;j++)
		{
			t[i][j]=0;
			for (int k=0;k<2;k++)
				t[i][j]=(t[i][j]+ksc(a[i][k],b[k][j]))%M;
		}
	for (int i=0;i<2;i++)
		for (int j=0;j<2;j++)
			a[i][j]=t[i][j];
}

void ksm(LL b)
{
	ret[0][0]=ret[1][1]=a[1][0]=1;
	for (;b;b>>=1,mul(a,a))
		if (b&1) mul(ret,a);
}

int main()
{	
	scanf("%I64d%I64d%I64d",&b,&d,&n);
	if (!n) {puts("1");return 0;}
	a[0][0]=b;a[0][1]=(d-b*b)>>2;
	ksm(n-1);
	ul ans=((ret[0][1]<<1)%M+ksc(ret[0][0],b))%M;
	if (b*b!=d&&(~n&1)) ans--;
	if (ans<0) ans+=M;
	cout<<ans<<endl;
	
	return 0;
}


T2

#include<iostream>
#include<algorithm>
#include<cstdlib>
#include<cstdio>
#include<string>
#include<cstring>
#include<ctime>
#include<cmath>
#define N 300005
#define LL long long
using namespace std;

int n,m;
int first[N],next[N];
int root[N],father[N];
LL h[N],a[N],v[N];
LL w[N],d[N],lc[N],rc[N],add[N],mul[N],as[N];
int p[N];
int ans1[N],ans2[N];

LL get_int()
{
	LL ret=0;char c=getchar();bool t=0;
	for (;(c<'0'||c>'9')&&c!='-';c=getchar());
	if (c=='-') c=getchar(),t=1;
	for (;c>='0'&&c<='9';c=getchar())
		ret=(ret<<1)+(ret<<3)+c-'0';
	return t ? -ret : ret;
}

void push_down(int x)
{
	int l=lc[x],r=rc[x];
	if (as[x]) {
		ans2[l]+=as[x],ans2[r]+=as[x];
		as[l]+=as[x],as[r]+=as[x],as[x]=0;
	}
	if (mul[x]^1) {
		w[l]*=mul[x],w[r]*=mul[x];
		mul[l]*=mul[x],mul[r]*=mul[x];
		add[l]*=mul[x],add[r]*=mul[x];
		mul[x]=1;
	}
	if (add[x]) {
		w[l]+=add[x],w[r]+=add[x];
		add[l]+=add[x],add[r]+=add[x];
		add[x]=0;
	}
}

int merge(int x,int y)
{
	if (!x) return y;
	if (!y) return x;
	if (w[x]>w[y]) swap(x,y);
	push_down(x);
	rc[x]=merge(rc[x],y);
	if (d[lc[x]]<d[rc[x]])
		swap(lc[x],rc[x]);
	d[x]=d[rc[x]]+1;
	return x;
}

void init()
{
	n=get_int();m=get_int();
	fill(mul+1,mul+m+1,1);
	for (int i=1;i<=n;i++) h[i]=get_int();
	for (int i=2;i<=n;i++)
	{
		father[i]=get_int();a[i]=get_int();v[i]=get_int();
		next[i]=first[father[i]];
		first[father[i]]=i;
	}
	int x;
	for (int i=1;i<=m;i++)
	{
		w[i]=get_int();x=get_int();
		root[x]=merge(root[x],i);
	}
}

void work()
{
	for (int x=n;x;x--)
	{
		int rt=root[x];
		for (int i=first[x];i;i=next[i])
			rt=merge(rt,root[i]);
		while (rt&&w[rt]<h[x])
		{
			push_down(rt);
			rt=merge(lc[rt],rc[rt]),ans1[x]++;
		}
		root[x]=rt;
		if (rt)
		{
			as[rt]++,ans2[rt]++;
			if (a[x]) w[rt]*=v[x],add[rt]*=v[x],mul[rt]*=v[x];
				else w[rt]+=v[x],add[rt]+=v[x];
		}
	}
	if (root[1])
	{
		int head=0,tail=1;
		p[1]=root[1];
		while (head^tail)
		{
			int x=p[++head];
			push_down(x);
			if (lc[x]) p[++tail]=lc[x];
			if (rc[x]) p[++tail]=rc[x];
		}
	}
}

int main()
{
	init();
	work();
	for (int i=1;i<=n;i++) printf("%d\n",ans1[i]);
	for (int i=1;i<=m;i++) printf("%d\n",ans2[i]);
	
	return 0;
}


T3

#include<iostream>
#include<algorithm>
#include<cstdlib>
#include<cstdio>
#include<string>
#include<cstring>
#include<ctime>
#include<cmath>
#define D double
#define eps 0.00001
#define N 505
using namespace std;

int n,m;
int w[N];
struct node{
	D z[N];int c; 
}a[N];

bool cmp(const node &a,const node &b)
{
	return a.c<b.c;
}

void init()
{
	scanf("%d%d",&n,&m);
	for (int i=1;i<=n;i++)
		for (int j=1;j<=m;j++)
			scanf("%lf",&a[i].z[j]);
	for (int i=1;i<=n;i++) scanf("%d",&a[i].c);
	sort(a+1,a+n+1,cmp);
}

void work()
{
	int num=0,ans=0;
	for (int i=1;i<=n;i++)
		for (int j=1;j<=m;j++)
			if (fabs(a[i].z[j])>eps)
			{
				if (w[j])
				{
					D t=a[i].z[j]/a[w[j]].z[j];
					for (int k=j;k<=m;k++)
						a[i].z[k]-=t*a[w[j]].z[k];
				}
				else
				{
					w[j]=i;
					num++;
					ans+=a[i].c;
					break;
				}
			}
	printf("%d %d\n",num,ans);
}

int main()
{
	init();
	work();
	
	return 0;
}





你可能感兴趣的:(总结)