Jloi 2015 一试

<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;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值