<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">T1</span>
观察式子,可以通过构造数列来推通项
然后剩下的就是矩阵乘法了
//Copyright(c)2015 liuchenrui
#include<cstdio>
#include<ctime>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#define ll unsigned long long
#define mod 7528443412579576937ull
using namespace std;
inline void splay(ll &v){
v=0;char c=0;ll p=1;
while(c<'0' || c>'9'){if(c=='-')p=-1;c=getchar();}
while(c>='0' && c<='9'){v=(v<<3)+(v<<1)+c-'0';c=getchar();}
v*=p;
}
ll b,d,n,A,B;
ll mul(ll a,ll b)
{
ll ans=0;a%=mod;
for(ll i=b;i;i>>=1,a=(a+a)%mod)
if(i&1)ans=(ans+a)%mod;
return ans;
}
struct M{
ll a[2][2];
M(){
memset(a,0,sizeof(a));
}
friend M operator * (M a,M b){
M ans;
for(int i=0;i<2;i++)
for(int j=0;j<2;j++)
for(int k=0;k<2;k++)
(ans.a[i][j]+=mul(a.a[i][k],b.a[k][j]))%=mod;
return ans;
}
friend M operator ^ (M a,ll b){
M ans;
ans.a[0][0]=ans.a[1][1]=1;
for(ll i=b;i;i>>=1,a=a*a)
if(i&1)ans=ans*a;
return ans;
}
}a,ans;
int main()
{
splay(b);splay(d);splay(n);
A=b;B=(d-b*b)/4;
a.a[0][1]=1;a.a[1][0]=B;a.a[1][1]=A;
ans.a[0][0]=2;ans.a[1][0]=b;
ll f=b*b!=d&&n%2==0?1:0;
cout<<(((a^n)*ans).a[0][0]-f+mod)%mod<<endl;
return 0;
}
T2
做法有2种
第一种打标记左偏堆,想想AHoi2009那道题,先乘后加,每次合并然后打上标记
从下到上,按照深度为关键字排序
复杂度n^log n
第二种链剖,线段树记录当前节点往后走的乘法和加法,还是想想AHoi那道题,线段树是一样的
复杂度n*log^2n
我写了第一种,因为pushdown打成了update。。调了一晚上,害怕写错加了很多不必要的地方,所以常数很大
至于多大嘛。。反正比n*log^2n 慢3倍。。体会一下
顺便说一句,每个点10秒能过,bzoj一共10秒。。这个嘛,,T了
//Copyright(c)2015 liuchenrui
#include<cstdio>
#include<ctime>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<queue>
#define ll long long
#define canspd(i) {if(C[i]!=1||J[i]!=0)pushdown(i);}
using namespace std;
inline void splay(ll &v){
v=0;char c=0;ll p=1;
while(c<'0' || c>'9'){if(c=='-')p=-1;c=getchar();}
while(c>='0' && c<='9'){v=(v<<3)+(v<<1)+c-'0';c=getchar();}
v*=p;
}
struct Edge{
ll to,next;
}edge[600010];
ll first[300010],size;
void addedge(ll x,ll y){
size++;
edge[size].to=y;
edge[size].next=first[x];
first[x]=size;
}
#define N 300010
ll root[N];
ll C[N],J[N];
ll ls[N],rs[N];
ll val[N],dis[N];
ll tot,n,m,fang[N];
ll deep[N],fa[N];
ll ans1[N],ans2[N];
ll a[N],v[N],sta[N];
void M(ll c,ll d,ll now){
if(now){
J[now]=c*J[now]+d;
C[now]*=c;
}
}
void pushdown(ll now){
val[now]=val[now]*C[now]+J[now];
M(C[now],J[now],ls[now]),M(C[now],J[now],rs[now]);
C[now]=1,J[now]=0;
}
void update(ll now){
pushdown(now);
if(dis[ls[now]]<dis[rs[now]])swap(ls[now],rs[now]);
dis[now]=dis[rs[now]]+1;
}
void merge(ll a,ll b){
canspd(a);canspd(b);
canspd(ls[a]);canspd(rs[a]);
canspd(ls[b]);canspd(rs[b]);
if(!rs[a]){
rs[a]=b;
update(b),update(a);
return;
}
if(val[b]<val[rs[a]])swap(rs[a],b);
merge(rs[a],b),update(rs[a]),update(ls[a]),update(a);
}
void join(ll a,ll b){//a.join(b)
pushdown(root[a]),pushdown(root[b]);
if(!root[a]){
root[a]=root[b];
root[b]=0;
return;
}
if(!root[b])return;
if(val[root[a]]>val[root[b]]){
merge(root[b],root[a]);
root[a]=root[b];root[b]=0;
}
else{
merge(root[a],root[b]);
root[b]=0;
}
}
void bfs(){
queue<ll>q;
q.push(1);
while(!q.empty()){
ll a=q.front();q.pop();
deep[a]=deep[fa[a]]+1;
for(ll u=first[a];u;u=edge[u].next){
q.push(edge[u].to);
}
}
}
void dfs(ll now){
if(!now)return;
ans2[now]=sta[now];
dfs(ls[now]),dfs(rs[now]);
C[now]=1;J[now]=0;
}
int main(){
int _q=30<<20;
char *_p=(char*)malloc(_q)+_q;
__asm__("movl %0, %%esp\n"::"r"(_p));
splay(n),splay(m);
for(ll i=1;i<=n;i++){
splay(fang[i]);
}
for(ll i=2;i<=n;i++){
splay(fa[i]);
splay(a[i]),splay(v[i]);
addedge(fa[i],i);
}
bfs();priority_queue< pair<ll,ll> >que;
for(ll i=1;i<=m;i++){
ll x,y;splay(x),splay(y);
if(x<fang[y]){
ans1[y]++;continue;
}
C[i]=1;sta[i]=deep[y];
val[i]=x,dis[i]=1;root[N-1]=i;
join(y,N-1);
que.push(make_pair(deep[y],y));
}
while(!que.empty()){
ll now=que.top().second;que.pop();
if(!root[now])continue;
pushdown(root[now]),pushdown(ls[root[now]]),pushdown(rs[root[now]]);
while(val[root[now]]<fang[now]&&root[now]){
ans1[now]++,ans2[root[now]]=sta[root[now]]-deep[now];
if(!ls[root[now]]&&rs[root[now]])root[now]=rs[root[now]];
else if(ls[root[now]]&&!rs[root[now]])root[now]=ls[root[now]];
else if(!ls[root[now]]&&!rs[root[now]]){root[now]=0;break;}
else{
if(val[ls[root[now]]]<val[rs[root[now]]])merge(ls[root[now]],rs[root[now]]),root[now]=ls[root[now]];
else merge(rs[root[now]],ls[root[now]]),root[now]=rs[root[now]];
}
pushdown(ls[root[now]]),pushdown(rs[root[now]]);
}
if(!root[now])continue;
if(now!=1){
que.push(make_pair(deep[fa[now]],fa[now]));
pushdown(root[now]);
if(a[now]==1)C[root[now]]=v[now];
else J[root[now]]=v[now];
join(fa[now],now);
}
else{
dfs(root[1]);root[1]=0;
}
}
for(ll i=1;i<=n;i++)printf("%lld\n",ans1[i]);
for(ll i=1;i<=m;i++)printf("%lld\n",ans2[i]);
}
T3
把每一个装备看成一个m维向量上的点,按照cost排序,每次贪心选出最优的哪个
怎么判断最优的那个呢,我们可以按照cost排序然后高斯消元,这样复杂度n^3
玄学:eps=1e-5 100pts;eps=1e-6 90pts;eps=1e-8 70pts;eps=1e-18 10pts
//Copyright(c)2015 liuchenrui
#include<cstdio>
#include<ctime>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#define ll long long
#define ul unsigned ll
#define H 23333333ull
#define eps 1e-5
#include<map>
using namespace std;
inline void splay(int &v){
v=0;char c=0;int p=1;
while(c<'0' || c>'9'){if(c=='-')p=-1;c=getchar();}
while(c>='0' && c<='9'){v=(v<<3)+(v<<1)+c-'0';c=getchar();}
v*=p;
}
int cost[505];
double a[505][505];
int n,m,ans,tot;
int ctr[505];
struct sorted{
int cost,id;
bool operator < (const sorted &b)const{
return cost<b.cost;
}
}s[505];
/*int gcd(int a,int b){
return b=0?a:gcd(b,a%b);
}
ul gethash(int x,int y){
static ul fid[505];
for(int i=1;i<=m;i++){
fid[i]=a[x][i]-a[y][i];
}
if(fid[1]<0){
for(int i=1;i<=m;i++){
fid[i]=-fid[i];
}
}
int g=fid[1];
for(int i=2;i<=m;i++)if(fid[i]!=0)g=gcd(g,abs(fid[i]));
for(int i=1;i<=m;i++)fid[i]/=g;
ul ret=17;
for(int i=1;i<=m;i++)ret=ret*H+(ul)fid[i];
return ret;
}*/
int main(){
splay(n),splay(m);
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
int x;splay(x);
a[i][j]=(double)x;
}
}
for(int i=1;i<=n;i++)splay(cost[i]);
/*for(int i=1;i<=n;i++){
for(int j=i;j<=n;j++){
dis[i][j]=dis[j][i]=gethash(i,j);
}
}*/
for(int i=1;i<=n;i++){
s[i].id=i;
s[i].cost=cost[i];
}
sort(s+1,s+n+1);
for(int i=1;i<=n;i++){
int v=s[i].id;
for(int j=1;j<=m;j++){
if(fabs(a[v][j])>eps){
if(ctr[j]==0){
ctr[j]=v;
ans++;tot+=cost[v];
break;
}
else{
double x=a[v][j]/a[ctr[j]][j];
for(int k=1;k<=m;k++){
a[v][k]-=x*a[ctr[j]][k];
}
}
}
}
}
cout<<ans<<" "<<tot<<endl;
}