151223
TJOI2015D1
T1 有意义的字符串
然后就可以矩阵快速幂求出an+1啦~
注意, 1.n=0时要特判,就是在这儿丢了5分。。。
2.模数非常大,必须开unsigned long long ,然后写快速乘
复杂度:O(23logNlogx)
需要的知识:二阶递推、矩阵乘法
T2 城池攻占
可并堆,从叶子往根合并,当堆顶值不满足时就弹出,每个点只加入一次、弹出一次。在树上每个节点改变值的时候,像双标记线段树一样,打lazy标记。
卡常。。。
复杂度 O(NlogN)
需要的知识:可并堆
T3 装备购买
复杂度: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; }
#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; }
#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; }