2018 Multi-University Training Contest 7

1001:Age of Moyu

在SPFA的时候开一个set或map记录一下转移到他的边的种类,转移的时候尽量选和当前这条边种类一样的边转移,玄学复杂度,记得fread读入挂和register进行常数优化。

 1 #include<bits/stdc++.h>
 2
 3 #define maxn 100000+5
 4 #define maxm 200000+5
 5
 6 using namespace std;
 7
 8 struct Edge{
 9     int u,v,c,nxt;
10 }e[maxm<<1];
11
12 unordered_map <int,int> s[maxn];
13
14 int head[maxn],dis[maxn],inq[maxn];
15 int ind,n,m;
16
17 void addedge(int x,int y,int c){
18     e[ind]=(Edge){x,y,c,head[x]},head[x]=ind++;
19     e[ind]=(Edge){y,x,c,head[y]},head[y]=ind++;
20 }
21
22 void spfa(){
23     queue <int> q;
24     dis[1]=0; q.push(1); inq[1]=1;
25     s[1][0]=1;
26     while(!q.empty()){
27         int x=q.front(); q.pop(); inq[x]=0;
28         for(int i=head[x];i!=-1;i=e[i].nxt){
29             int flag=1;
30             if(s[x][e[i].c]) flag=0;
31             if(dis[e[i].v]>dis[x]+flag){
32                 dis[e[i].v]=dis[x]+flag;
33                 s[e[i].v].clear();
34                 if(!s[e[i].v][e[i].c]) s[e[i].v][e[i].c]=1;
35                 if(!inq[e[i].v]){
36                     inq[e[i].v]=1;
37                     q.push(e[i].v);
38                 }
39             }
40             else if(dis[e[i].v]==dis[x]+flag){
41                 if(!s[e[i].v][e[i].c]) {
42                     s[e[i].v][e[i].c]=1;
43                     if(!inq[e[i].v]){
44                         inq[e[i].v]=1;
45                         q.push(e[i].v);
46                     }
47                 }
48             }
49         }
50     }
51     if(dis[n]!=0x3f3f3f3f) printf("%d\n",dis[n]);
52     else puts("-1");
53 }
54
55 namespace fastIO {
56     #define BUF_SIZE 100000
57     bool IOerror = 0;
58     inline char nc() {
59         static char buf[BUF_SIZE], *p1 = buf + BUF_SIZE, *pend = buf + BUF_SIZE;
60         if(p1 == pend) {
61             p1 = buf;
62             pend = buf + fread(buf, 1, BUF_SIZE, stdin);
63             if(pend == p1) {
64                 IOerror = 1;
65                 return -1;
66             }
67         }
68         return *p1++;
69     }
70     inline bool blank(char ch) {
71         return ch == ‘ ‘ || ch == ‘\n‘ || ch == ‘\r‘ || ch == ‘\t‘;
72     }
73     inline int rd(int &x) {
74         char ch;
75         while(blank(ch = nc()));
76         if(IOerror) return -1;
77         for(x = ch - ‘0‘; (ch = nc()) >= ‘0‘ && ch <= ‘9‘; x = x * 10 + ch - ‘0‘);
78         return 1;
79     }
80     #undef BUF_SIZE
81 };
82 using namespace fastIO;
83
84 int main(){
85     freopen("x.in","r",stdin);
86     while(~rd(n)){
87         rd(m);
88         ind=0;
89         for(register int i=1;i<=n;i++) inq[i]=0,dis[i]=0x3f3f3f3f,head[i]=-1;
90         for(register int i=1;i<=m;i++){
91             int x,y,c;
92             rd(x); rd(y); rd(c);
93             addedge(x,y,c);
94         }
95         spfa();
96     }
97     return 0;
98 }

1002:AraBellaC

枚举循环周期,对每个循环周期内的mxa,mnb,mxb,mnc二分寻找,要保证(mxa-1)%len<(mnb-1)%len和(mxb-1)%len<(mnc-1)%len。

#include <cstdio>
#include <cstring>
#include <queue>
#include <algorithm>
#include <cmath>
#include <vector>
#include <iostream>
#include <stack>
#include <set>
#include <map>
using namespace std;

const int MAX=1e5+5;
int t,m;
int a,b,c;
vector<int> E[3];

void update(int aa,int bb,int cc){
    int flag=0;
    if(aa<a) flag=1;
    else if(aa==a&&bb<b) flag=1;
    else if(aa==a&&bb==b&&cc<c) flag=1;
    if(flag) a=aa,b=bb,c=cc;
}

int main(){
    int i,j;

    //freopen("data.in","r",stdin);
    scanf("%d",&t);
    while(t--){
        int mx=0;
        a=b=c=0x3f3f3f3f;
        for(i=0;i<3;i++) E[i].clear(),E[i].push_back(0);
        scanf("%d",&m);
        for(i=0;i<m;i++){
            int pos;char c;
            scanf("%d %c",&pos,&c);
            E[c-‘A‘].push_back(pos);
            mx=max(mx,pos);
        }
        for(i=0;i<3;i++) E[i].push_back(MAX),sort(E[i].begin(),E[i].end());
        for(i=1;i<=mx;i++){
            int mxa=0,mnc=MAX,mxb=0,mnb=MAX;
            for(j=(mx+i-1)/i;j>0;j--){
                int tmp=*(upper_bound(E[0].begin(),E[0].end(),j*i)-1);
                if(tmp>(j-1)*i) mxa=max(mxa,(tmp-1)%i);
                tmp=*upper_bound(E[1].begin(),E[1].end(),(j-1)*i);
                if(tmp<=j*i) mnb=min(mnb,(tmp-1)%i);
                tmp=*(upper_bound(E[1].begin(),E[1].end(),j*i)-1);
                if(tmp>(j-1)*i) mxb=max(mxb,(tmp-1)%i);
                tmp=*upper_bound(E[2].begin(),E[2].end(),(j-1)*i);
                if(tmp<=j*i) mnc=min(mnc,(tmp-1)%i);
                if(mxa>=mnb||mxb>=mnc) break;
            }
            if(j==0) update(mxa+1,mxb-mxa,i-mxb-1);
        }
        if(a==0x3f3f3f3f) puts("NO");
        else printf("%d %d %d\n",a,b,c);
    }

    return 0;
} 

1005:GuGuFishtion

首先推公式,欧拉函数是积性函数但不是一个完全积性函数,所以a,b不互质的情况下肯定还有一个偏移量。然后质因数分解一下a,b可以用数论知识证明差一个GCD(a,b)/Φ(GCD(a,b)),所以对于所有a,b不互质的情况下对答案的贡献是GCD(a,b)/Φ(GCD(a,b)),互质的话贡献是1。然后容斥,枚举k,容斥计算以k作为gcd的数对有多少个,然后乘上贡献就行了。

#include<bits/stdc++.h>

using namespace std;

typedef long long LL;

const int N=1000000+5;

LL tmp,ans;
long long n,m,p;
long long phi[N], cnt, prime[N/3],dy[N], val[N], q[N],sum_val[N],sum[N],inv[N],mu[N];
bool com[N];

int primes;
void get_prime_phi(){
   memset( com, false, sizeof( com ) );
    primes = 0;
    phi[1] = 1;
    mu[1] = 1;
    for (int i = 2; i < N; ++i){
        if (!com[i]) {
            prime[primes++] = i;
            phi[i] = i-1;
            mu[i] = -1;
        }
        for (int j = 0; j < primes && i*prime[j] <= N; ++j){
            com[i*prime[j]] = true;
            if (i % prime[j]){
                phi[i*prime[j]] = phi[i]*(prime[j]-1);
                mu[i*prime[j]] = -mu[i];
            }
            else {
                mu[i*prime[j]] = 0;
                phi[i*prime[j]] = phi[i]*prime[j];
                break;
            }
        }
    }
}

int lim;
long long f[N],F[N];

void get(){
    for(int i=1;i<=lim;++i)   F[i]=1ll*(m/i)*(n/i)%p;
    for(int i=lim;i>0;--i){
            f[i]=F[i];
        for(int j=i+i;j<=lim;j+=i)
            f[i]-=1ll*f[j]%p;
    }
    for(int i=1;i<=lim;++i)   f[i]%=p;
}

int main(){
    //freopen("case.in","r",stdin);
    int T;
    scanf("%d",&T);
    get_prime_phi();

    while(T--){
        scanf("%lld%lld%lld",&n,&m,&p); tmp=ans=0;
        lim=min(n,m);
        memset(inv,0,sizeof(inv));
        memset(f,0,sizeof(f));
        inv[1]=1;
        for(register int i=2;i<=lim+2;i++)
            inv[i]=(LL)(p-p/i)*inv[p%i]%p;
        get();

        for(register int i=1;i<=lim;i++){
            val[i]=(LL)i*inv[phi[i]]%p;
            ans=(ans+(LL)val[i]*f[i]%p)%p;
            if(ans<0) ans+=p;
            //cout<<ans<<endl;
        }

        printf("%lld\n",ans);
    }
    return 0;
}

1006:Lord Li‘s problem

有意思的dp;
根据异或的性质,X_0⊕X_1⊕X_2⊕X_3⊕…..⊕X_(M-1)=S⊕T
计算出S⊕T中一共有cnt个1,将这个二进制数标准化,使它成为前面N-cnt个0,后cnt个1的二进制数,答案保持不变,问题变为:用K个N位且有3个1的不同二进制数进行异或,最终得到前面N-cnt个0,后面cnt个1这个二进制数,有多少种方案?
递推。设d[K][M]表示用K个N位且有3个1的不同二进制数进行异或,最终得到前面N-cnt个0,后面cnt个1这个二进制数的方案数。然后可以容易推出状态只可以从上一层的-1,-3,+1,+3这些状态转移过来
考虑加入重复串的影响,d[i][j]-= (d[i-2][j] * (C[n][3]-i+2);表示去除加入i-2个数字并且后面有j个1这个二进制数但后来又异或上两个之前没用过的相同的数的方案数,
考虑二进制数加入的先后顺序给答案带来的额外贡献,d[i][j]=d[i][j]*inv[i]%mod 

#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#include <vector>
#include <string>
#include <map>
using namespace std;
const long long mod=19260817;

long long dp[30][50],c[50][50],inv[110];
char S[45],T[45];
int n,k;

void init()
{
    memset(dp,0,sizeof(dp));
}

int main()
{
    int i,j;
    c[0][0]=1;
    for(i=1;i<=45;i++)
    {
        c[i][0]=c[i][i]=1;
        for(j=1;j<i;j++)
        {
            c[i][j]=(c[i-1][j]+c[i-1][j-1])%mod;
        }
    }

    inv[1]=1;
    for(i=2;i<=60;i++)
        inv[i]=(mod-mod/i)*inv[mod%i]%mod;

    int cas=1;
    while(scanf("%d%d",&n,&k)!=EOF)
    {
        if(n==0&&k==0) break;
        init();
        scanf("%s%s",S,T);
        int num_1=0;
        for(i=0;i<n;i++)
            if((S[i]-‘0‘)^(T[i]-‘0‘)==1) num_1++;
        dp[0][0]=1;
        for(i=1;i<=k;i++)
        {
            for(j=0;j<=n;j++)
            {
                if(j>=3) dp[i][j]=(dp[i][j]+dp[i-1][j-3]*c[j][3])%mod;
                if(j>=1) dp[i][j]=(dp[i][j]+dp[i-1][j-1]*c[j][2]%mod*c[n-j][1])%mod;
                if(j+3<=n) dp[i][j]=(dp[i][j]+dp[i-1][j+3]*c[n-j][3])%mod;
                if(j+1<=n) dp[i][j]=(dp[i][j] + dp[i - 1][j + 1] * c[j][1] %mod* c[n - j][2]) % mod;
                if (i - 2 >= 0)dp[i][j] = (dp[i][j] - (dp[i - 2][j] * (c[n][3] - i + 2))) % mod;
                dp[i][j] = dp[i][j] * inv[i] % mod;
                if(dp[i][j]<0) dp[i][j]+=mod;
            }
        }
        printf("Case #%d: %lld\n",cas++, dp[k][num_1]);
    }
    return 0;
}

1007:Reverse Game

1008:Traffic Network in Numazu

将环上的一个节点定为根节点,根节点连在的环上的一条边切开,得到一颗树,将树的权值按dfs序排列,用树状数组动态维护。若查询节点的lca不经过环,则直接为树上的距离,若经过环,可在两点在树上的距离以及绕环走的距离中取一个最小值作为答案,这些都可通过与LCA相关的计算得出,细节处理见代码。

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<cstdlib>
  4 #include<algorithm>
  5
  6 #define maxn 100000+5
  7
  8 using namespace std;
  9
 10 struct Edge{
 11     int u,v,c,nxt;
 12 }e[maxn<<1];
 13
 14 int dfn[maxn<<1]; long long bit[maxn<<1];
 15 int data[maxn][3],fa[maxn][20],st[maxn],ed[maxn],head[maxn],flag[maxn],tag[maxn],du[maxn],dep[maxn];
 16 int n,q,ind,root,cut,leaf,pos;
 17
 18 void addedge(int x,int y,int z){
 19     e[ind]=(Edge){x,y,z,head[x]},head[x]=ind++;
 20     e[ind]=(Edge){y,x,z,head[y]},head[y]=ind++;
 21 }
 22
 23 int findroot(int x,int p){
 24     tag[x]++;
 25     if(tag[x]==2){
 26         root=x; leaf=p; flag[x]=1;
 27         return 1;
 28     }
 29     for(int i=head[x];i!=-1;i=e[i].nxt)
 30         if(e[i].v!=p){
 31             int tmp=findroot(e[i].v,x);
 32             if(tmp==1){
 33                 cut=i; flag[x]=1;
 34                 return 2;
 35             }
 36             else if(tmp==2){
 37                 flag[x]=1;
 38                 if(tag[x]==2) return 3;
 39                 return 2;
 40             }
 41             else if(tmp==3) return 3;
 42         }
 43     return 0;
 44 }
 45
 46 void dfs(int x,int p){
 47     for(int i=head[x];i!=-1;i=e[i].nxt)
 48         if(e[i].v!=p && i!=cut && i!=(cut^1)){
 49             fa[e[i].v][0]=x; dep[e[i].v]=dep[x]+1;
 50             dfn[++pos]=e[i].c; st[e[i].v]=pos;
 51             dfs(e[i].v,x);
 52             dfn[++pos]=-e[i].c; ed[e[i].v]=pos;
 53         }
 54 }
 55
 56 void add(int x,int val){
 57     int N=maxn<<1;
 58     while(x<N){
 59         bit[x]+=val;
 60         x+=x&-x;
 61     }
 62 }
 63
 64 long long sum(int x){
 65     long long res=0;
 66     while(x){
 67         res+=bit[x];
 68         x-=x&-x;
 69     }
 70     return res;
 71 }
 72
 73 void init(){
 74     for(int i=1;i<20;i++)
 75         for(int j=1;j<=n;j++)
 76             fa[j][i]=fa[fa[j][i-1]][i-1];
 77     for(int i=1;i<=pos;i++)
 78         add(i,dfn[i]);
 79
 80 }
 81
 82 int getlca(int x,int y){
 83
 84     if(dep[x]>dep[y]) swap(x,y);
 85     for(int i=19;i>=0;i--) if((dep[y]-dep[x])&(1<<i)) y=fa[y][i];
 86     if(x==y) return x;
 87     for(int i=19;i>=0;i--)
 88         if(fa[x][i]!=fa[y][i]){
 89             x=fa[x][i];
 90             y=fa[y][i];
 91         }
 92     return fa[x][0];
 93 }
 94
 95 int main(){
 96 #ifndef ONLINE_JUDGE
 97     freopen("x.in","r",stdin);
 98     freopen("x.out","w",stdout);
 99 #endif
100     int T;
101     scanf("%d",&T);
102     while(T--){
103         scanf("%d%d",&n,&q); pos=ind=0;
104         for(int i=1;i<=n;i++){
105             head[i]=-1;
106             tag[i]=du[i]=bit[i]=bit[i+n]=flag[i]=0;
107             for(int j=0;j<20;j++) fa[i][j]=0;
108         }
109         for(int i=1;i<=n;i++){
110             int x,y,c;
111             scanf("%d%d%d",&x,&y,&c);
112             addedge(x,y,c); du[x]++; du[y]++;
113             data[i][0]=x; data[i][1]=y; data[i][2]=c;
114         }
115         bool fg=false;
116         for(int i=1;i<=n;i++)
117             if(du[i]==1){ fg=true; findroot(i,0); break; }
118         if(!fg) findroot(1,0);
119         dep[root]=1; st[root]=0;
120         dfs(root,0);
121         init();
122         for(int i=1;i<=q;i++){
123             int op,x,y;
124             scanf("%d%d%d",&op,&x,&y);
125             if(op==0){
126                 if(cut/2+1==x){ data[x][2]=y; continue; }
127                 int a=data[x][0],b=data[x][1];
128                 if(dep[a]<dep[b]) swap(a,b);
129                 add(st[a],-data[x][2]); add(ed[a],data[x][2]);
130                 data[x][2]=y;
131                 add(st[a],data[x][2]); add(ed[a],-data[x][2]);
132             }
133             else{
134                 int p=getlca(x,y);
135                 long long ans=sum(st[x])+sum(st[y])-sum(st[p])*2;
136                 if(flag[p]){
137                     int px=getlca(x,leaf),py=getlca(y,leaf);
138                     if(dep[px]<dep[py]) swap(x,y),swap(px,py);
139                     long long tmp=sum(st[x])+sum(st[leaf])-sum(st[px])*2+sum(st[y])+data[cut/2+1][2];
140                     printf("%lld\n",min(tmp,ans));
141                 }
142                 else printf("%lld\n",ans);
143             }
144         }
145     }
146     return 0;
147 }

1009:Tree

将每个点向上跳能到达的节点标记为一个新的父节点,根据这个新的父节点能建出一颗新树,根节点表示为能跳到原树的外部,故答案即为某个点的深度。为了动态维护这颗树,可以考虑使用LCT维护,通知记录子树的大小,Access后子树大小即为所求点的深度。

  1 #include<bits/stdc++.h>
  2
  3 #define maxn 100000+5
  4
  5 using namespace std;
  6
  7 struct Edge{
  8     int u,v,nxt;
  9 }e[maxn<<1];
 10
 11 struct Splay_Tree{
 12     int ch[2];
 13     int sz,flip,fa,pf;
 14     void init(){
 15         ch[0]=ch[1]=sz=flip=fa=pf=0;
 16     }
 17 }tr[maxn<<1];
 18
 19 int st[maxn],head[maxn],mf[maxn],dep[maxn],fa[maxn][20];
 20 int n,q,top,ind;
 21
 22 inline int in(){
 23     int x=0; char ch=getchar();
 24     for(;!isdigit(ch);ch=getchar());
 25     for(; isdigit(ch);ch=getchar()) x=x*10+ch-‘0‘;
 26     return x;
 27 }
 28
 29 inline void Pushdown(int k){
 30     if(tr[k].flip){
 31         tr[k].flip^=1;
 32         tr[tr[k].ch[0]].flip^=1;
 33         tr[tr[k].ch[1]].flip^=1;
 34         swap(tr[k].ch[0],tr[k].ch[1]);
 35     }
 36 }
 37
 38 inline void Update(int k){
 39     tr[k].sz=tr[tr[k].ch[0]].sz+tr[tr[k].ch[1]].sz+1;
 40 }
 41
 42 void Rotate(int &k,int d){
 43     int t=tr[k].ch[d^1],Fa=tr[k].fa,Pf=tr[k].pf;
 44     tr[k].pf=0; tr[k].fa=t;    tr[tr[t].ch[d]].fa=k;
 45     tr[t].pf=Pf; tr[t].fa=Fa;
 46     tr[k].ch[d^1]=tr[t].ch[d]; tr[t].ch[d]=k;
 47     Update(k); Update(t); k=t;
 48 }
 49
 50 void Splay(int &k,int x){
 51     int d1=(tr[tr[k].ch[0]].sz<x?1:0),t=tr[k].ch[d1];
 52     if(d1==1) x-=tr[tr[k].ch[0]].sz+1;
 53     if(x){
 54         int d2=(tr[tr[t].ch[0]].sz<x?1:0);
 55         if(d2==1) x-=tr[tr[t].ch[0]].sz+1;
 56         if(x){
 57             Splay(tr[t].ch[d2],x);
 58             if(d1==d2) Rotate(k,d1^1);
 59             else Rotate(tr[k].ch[d1],d1);
 60         }
 61         Rotate(k,d1^1);
 62     }
 63 }
 64
 65 int rankk(int k,int &rt){
 66     int res=tr[tr[k].ch[0]].sz+1;
 67     st[++top]=k; rt=k;
 68     while(tr[k].fa){
 69         int p=tr[k].fa;
 70         st[++top]=p;
 71         if(tr[p].ch[0]!=k)
 72             res+=tr[tr[p].ch[0]].sz+1;
 73         k=p;
 74     }
 75     rt=k;
 76     return res;
 77 }
 78
 79 inline void Haha(int k){
 80     int rt,x=rankk(k,rt);
 81     while(top) Pushdown(st[top--]);
 82     Splay(rt,x);
 83 }
 84
 85 inline void Cutright(int k){
 86     if(tr[k].ch[1]){
 87         tr[tr[k].ch[1]].pf=k;
 88         tr[tr[k].ch[1]].fa=0;
 89         tr[k].ch[1]=0;
 90     }
 91 }
 92
 93 void Access(int k){
 94     Haha(k); Cutright(k);
 95     while(tr[k].pf){
 96         int u=tr[k].pf;
 97         Haha(u); Cutright(u);
 98         tr[u].ch[1]=k;
 99         tr[k].pf=0; tr[k].fa=u;
100         Update(u); k=u;
101     }
102 }
103
104 inline void Beroot(int k){
105     Access(k); Haha(k);
106     tr[k].flip^=1;
107 }
108
109 inline void Cut(int k){
110     Access(k); Haha(k);
111     int l=tr[k].ch[0];
112     tr[k].ch[0]=0;
113     if(l){
114         tr[l].fa=0;
115         tr[l].pf=0;
116         Update(k);
117         Haha(l);
118     }
119 }
120
121 inline void Link(int k,int p){
122     Access(k); Beroot(p);
123     tr[p].pf=k;
124 }
125
126 void dfs(int x,int fa){
127     for(int i=head[x];i!=-1;i=e[i].nxt)
128         if(e[i].v!=fa){
129             dep[e[i].v]=dep[x]+1;
130             dfs(e[i].v,x);
131         }
132
133 }
134
135 void init(){
136     for(int i=1;i<20;i++)
137         for(int j=1;j<=n;j++)
138             fa[j][i]=fa[fa[j][i-1]][i-1];
139 }
140
141 int da(int x,int k){
142     for(int i=19;i>=0;i--) if(k&(1<<i)) x=fa[x][i];
143     return x;
144 }
145
146 void addedge(int x,int y){
147     e[ind]=(Edge){x,y,head[x]},head[x]=ind++;
148 }
149
150 int main(){
151     int T;
152     T=in();
153     while(T--){
154         n=in();
155         memset(fa,0,sizeof(fa));
156         for(int i=1;i<=n+1;i++) tr[i].init();
157         ind=top=0;
158         tr[1].sz=tr[n+1].sz=1; tr[1].pf=n+1;
159         for(int i=1;i<=n;i++) head[i]=-1;
160         for(int i=2;i<=n;i++){
161             int x=in(); fa[i][0]=x;
162             addedge(x,i); tr[i].sz=1;
163         }
164         for(int i=1;i<=n;i++) mf[i]=in();
165         dfs(1,0); init();
166         for(int i=1;i<=n;i++){
167             if(mf[i]>dep[i]){
168                 tr[i].pf=n+1;
169                 continue;
170             }
171             int p=da(i,mf[i]);
172             tr[i].pf=p;
173         }
174         q=in();
175         for(int i=1;i<=q;i++){
176             int op,x,y,newa;
177             op=in(); x=in();
178             if(op==1){
179                 Beroot(n+1);
180                 Access(x); Haha(x);
181                 printf("%d\n",tr[tr[x].ch[0]].sz);
182             }
183             else{
184                 newa=in(); Cut(x);
185                 if(newa>dep[x]) Link(n+1,x);
186                 else{
187                     y=da(x,newa);
188                     Link(y,x);
189                 }
190             }
191         }
192     }
193     return 0;
194 }

1010:Sequence

矩阵快速幂,首先可以看出这题只能用矩阵快速幂,然后考虑对p进行分块,处理出p/i这个矩阵的指数,然后就矩阵快速幂了

#include <cstdio>
#include <cstring>
#include <queue>
#include <algorithm>
#include <cmath>
#include <vector>
#include <iostream>
#include <stack>
#include <set>
#include <map>
using namespace std;

const int MAX=5;
const int mod=1e9+7;

struct Matrix{
    long long mp[MAX][MAX];  //矩阵
    int n,m;  //行 列 

    Matrix(int _n,int _m){
        n=_n,m=_m;
        for(int i=0;i<n;i++)
            for(int j=0;j<m;j++)
                mp[i][j]=0;
    }

    Matrix operator+(const Matrix &b)const{
        Matrix tmp(n,m);
        for(int i=0;i<n;i++)
            for(int j=0;j<m;j++){
                tmp.mp[i][j]=mp[i][j]+b.mp[i][j];
                tmp.mp[i][j]%=mod;
            }
        return tmp;
    }

    Matrix operator*(const Matrix &b)const{
        Matrix ret(n,b.m);
        for(int i=0;i<n;i++)
            for(int j=0;j<m;j++)
                for(int k=0;k<m;k++){
                    ret.mp[i][j]+=mp[i][k]*b.mp[k][j];
                    ret.mp[i][j]%=mod;
                }
        return ret;
    }

    Matrix operator^(long long k)const{
        Matrix ret(n,m),b(n,m);
        for(int i=0;i<n;i++){
            for(int j=0;j<m;j++)
                b.mp[i][j]=mp[i][j];
            ret.mp[i][i]=1;
        }
        while(k){
            if(k&1)
                ret=ret*b;
            b=b*b;
            k>>=1;
        }
        return ret;
    }
};

int t;
int a,b,c,d,p,n;

int main(){
    int i;

    scanf("%d",&t);
    while(t--){
        scanf("%d%d%d%d%d%d",&a,&b,&c,&d,&p,&n);
        if(n==1) printf("%d\n",a);
        else if(n==2) printf("%d\n",b);
        else{
            Matrix mc(3,1);
            mc.mp[0][0]=b;
            mc.mp[1][0]=a;
            mc.mp[2][0]=1;
            int now=3;
            Matrix mb(3,3);
            mb.mp[0][0]=d,mb.mp[0][1]=c,mb.mp[1][0]=1,mb.mp[2][2]=1;
            while(now<=n){
                int tmp=p/now;
                mb.mp[0][2]=tmp;
                if(tmp==0){
                    mc=(mb^(n-now+1))*mc;
                    break;
                }
                int x=p/tmp;
                if(x>n) x=n;
                mc=(mb^(x-now+1))*mc;
                now=x+1;
            }
            printf("%lld\n",mc.mp[0][0]);
        }
    }

    return 0;
} 

1011:Swordsman

瞎贪就行,按每个关键字开优先队列,直到从最后一个队列弹出表示可以击杀,同时加上exp就好。

#include <cstdio>
#include <cstring>
#include <queue>
#include <algorithm>
#include <cmath>
#include <vector>
#include <iostream>
#include <stack>
#include <set>
#include <map>
using namespace std;

struct FastIO
{
    static const int S = 200;
    int wpos;
    char wbuf[S];
    FastIO() :wpos(0) {}
    inline int xchar()
    {
        static char buf[S];
        static int len = 0, pos = 0;
        if (pos == len) pos = 0, len = fread(buf, 1, S, stdin);
        if (pos == len) exit(0);
        return buf[pos++];
    }
    inline int read()
    {
        int s = 1, c = xchar(), x = 0;
        while (c <= 32) c = xchar();
        if (c == ‘-‘) s = -1, c = xchar();
        for (; ‘0‘ <= c && c <= ‘9‘; c = xchar()) x = x * 10 + c - ‘0‘;
        return x * s;
    }
    ~FastIO()
    {
        if (wpos) fwrite(wbuf, 1, wpos, stdout), wpos = 0;
    }
}io;

const int MAX=1e5+5; 

int t,n,k,ans;
struct node{
    int x[10],y[10];
}mon[MAX];
int v[10];

struct cmpa{
    bool operator()(node a,node b){
        return a.x[0]>b.x[0];
    }
};
struct cmpb{
    bool operator()(node a,node b){
        return a.x[1]>b.x[1];
    }
};
struct cmpc{
    bool operator()(node a,node b){
        return a.x[2]>b.x[2];
    }
};
struct cmpd{
    bool operator()(node a,node b){
        return a.x[3]>b.x[3];
    }
};
struct cmpe{
    bool operator()(node a,node b){
        return a.x[4]>b.x[4];
    }
};

priority_queue<node,vector<node>,cmpa> a;
priority_queue<node,vector<node>,cmpb> b;
priority_queue<node,vector<node>,cmpc> c;
priority_queue<node,vector<node>,cmpd> d;
priority_queue<node,vector<node>,cmpe> e;

int main(){
    int i,j;

    //freopen("1.in","r",stdin);
    //freopen("10.out","w",stdout);
    t=io.read();
    while(t--){
        ans=0;
        while(!a.empty()) a.pop();
        while(!b.empty()) b.pop();
        while(!c.empty()) c.pop();
        while(!d.empty()) d.pop();
        while(!e.empty()) e.pop();
        n=io.read(),k=io.read();
        for(i=0;i<k;i++) v[i]=io.read();
        for(i=0;i<n;i++){
            for(j=0;j<k;j++) mon[i].x[j]=io.read();
            for(j=0;j<k;j++) mon[i].y[j]=io.read();
            a.push(mon[i]);
        }
        if(k==1){
            while(!a.empty()){
                node now=a.top();
                if(v[0]>=now.x[0]){
                    ans++;
                    a.pop();
                    v[0]+=now.y[0];
                }
                else break;
            }
        }
        else if(k==2){
            while(!a.empty()){
                node now=a.top();
                if(v[0]>=now.x[0]){
                    a.pop();
                    b.push(now);
                    while(!b.empty()){
                        node now=b.top();
                        if(v[1]>=now.x[1]){
                            ans++;
                            b.pop();
                            v[0]+=now.y[0];
                            v[1]+=now.y[1];
                        }
                        else break;
                    }
                }
                else break;
            }
        }
        else if(k==3){
            while(!a.empty()){
                node now=a.top();
                if(v[0]>=now.x[0]){
                    a.pop();
                    b.push(now);
                    while(!b.empty()){
                        node now=b.top();
                        if(v[1]>=now.x[1]){
                            b.pop();
                            c.push(now);
                            while(!c.empty()){
                                node now=c.top();
                                if(v[2]>=now.x[2]){
                                    ans++;
                                    c.pop();
                                    v[0]+=now.y[0];
                                    v[1]+=now.y[1];
                                    v[2]+=now.y[2];
                                }
                                else break;
                            }
                        }
                        else break;
                    }
                }
                else break;
            }
        }
        else if(k==4){
            while(!a.empty()){
                node now=a.top();
                if(v[0]>=now.x[0]){
                    a.pop();
                    b.push(now);
                    while(!b.empty()){
                        node now=b.top();
                        if(v[1]>=now.x[1]){
                            b.pop();
                            c.push(now);
                            while(!c.empty()){
                                node now=c.top();
                                if(v[2]>=now.x[2]){
                                    c.pop();
                                    d.push(now);
                                    while(!d.empty()){
                                        node now=d.top();
                                        if(v[3]>=now.x[3]){
                                            ans++;
                                            d.pop();
                                            v[0]+=now.y[0];
                                            v[1]+=now.y[1];
                                            v[2]+=now.y[2];
                                            v[3]+=now.y[3];
                                        }
                                        else break;
                                    }
                                }
                                else break;
                            }
                        }
                        else break;
                    }
                }
                else break;
            }
        }
        else if(k==5){
            while(!a.empty()){
                node now=a.top();
                if(v[0]>=now.x[0]){
                    a.pop();
                    b.push(now);
                    while(!b.empty()){
                        node now=b.top();
                        if(v[1]>=now.x[1]){
                            b.pop();
                            c.push(now);
                            while(!c.empty()){
                                node now=c.top();
                                if(v[2]>=now.x[2]){
                                    c.pop();
                                    d.push(now);
                                    while(!d.empty()){
                                        node now=d.top();
                                        if(v[3]>=now.x[3]){
                                            d.pop();
                                            e.push(now);
                                            while(!e.empty()){
                                                node now=e.top();
                                                if(v[4]>=now.x[4]){
                                                    ans++;
                                                    e.pop();
                                                    v[0]+=now.y[0];
                                                    v[1]+=now.y[1];
                                                    v[2]+=now.y[2];
                                                    v[3]+=now.y[3];
                                                    v[4]+=now.y[4];
                                                }
                                                else break;
                                            }
                                        }
                                        else break;
                                    }
                                }
                                else break;
                            }
                        }
                        else break;
                    }
                }
                else break;
            }
        }

        printf("%d\n",ans);
        for(i=0;i<k;i++) printf("%d%c",v[i],i==k-1?‘\n‘:‘ ‘);
    }

    return 0;
} 

原文地址:https://www.cnblogs.com/Hetui/p/9477405.html

时间: 2024-08-13 16:12:42

2018 Multi-University Training Contest 7的相关文章

2018 Nowcoder Multi-University Training Contest 2

Practice Link A. run 题意: 白云每次可以移动\(1\)米或者\(k\)米,询问移动的米数在\([L, R]\)范围内的方案数有多少. 思路: \(dp[i][2]\)表示到第\(i\)米,是通过\(1\)米的方式过来的还是\(k\)米的方式过来的,递推即可. 代码: #include <bits/stdc++.h> using namespace std; #define N 100010 const int p = 1e9 + 7; int f[N][2], g[N];

2018 Nowcoder Multi-University Training Contest 1

Practice Link J. Different Integers 题意: 给出\(n\)个数,每次询问\((l_i, r_i)\),表示\(a_1, \cdots, a_i, a_j, \cdots, a_n\)中有多少个不同的数. 思路: 先分别离线求出\(a_1, \cdots a_i\)以及\(a_j, \cdots, a_n\)中有多少个不同的数. 再考虑有多少个数既在\([1, i]\)中也在\([j, n]\)中,再离线做一次. 考虑一个数第一次出现的时候,那么这个数下一次出现

2018 Nowcoder Multi-University Training Contest 5

Practice Link A. gpa 题意: 有\(n\)门课程,每门课程的学分为\(s_i\),绩点为\(c_i\),要求最多删除\(k\)门课程,使得gpa最高. gpa计算方式如下: \[ \begin{eqnarray*} gpa = \frac{\sum s_ic_i}{\sum s_i} \end{eqnarray*} \] 思路: 首先删去的课程越多,gpa肯定不会变得更差. 所以我们肯定是删去\(k\)门课程. 考虑二分答案,check的时候要满足: \[ \begin{eq

HDU 2018 Multi-University Training Contest 3 Problem A. Ascending Rating 【单调队列优化】

任意门:http://acm.hdu.edu.cn/showproblem.php?pid=6319 Problem A. Ascending Rating Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 524288/524288 K (Java/Others)Total Submission(s): 5943    Accepted Submission(s): 2004 Problem Description Before

杭电2018多校第一场(2018 Multi-University Training Contest 1) 1001.Maximum Multiple (HDU6298)-数学思维题(脑子是个好东西,可惜我没有)

暑假杭电多校第一场,这一场是贪心场,很多贪心的题目,但是自己太菜,姿势挫死了,把自己都写吐了... 2018 Multi-University Training Contest 1 HDU6298.Maximum Multiple 题目意思就是给你一个n,找出来三个数x,y,z, 使得n=x+y+z,而且x,y,z都是n的因数,并且x*y*z为最大值,让你输出来x*y*z的最大值.如果没有满足条件的情况就输出-1. 由1=1/2+1/3+1/6=1/3+1/3+1/3=1/2+1/4+1/4,所

2018 Multi-University Training Contest 4

Problem D. Nothing is Impossible Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others)Total Submission(s): 504    Accepted Submission(s): 302 Problem Description m students, including Kazari, will take an exam tomorrow

HDU 6396 Swordsman --------2018 Multi-University Training Contest 7 (模拟+读入挂)

原题地址: 打怪升级 一开始有N个怪物:主角有K个能力:只有K个能力都击败怪物才能斩杀怪物并获得K个能力的增值:问最多能杀几个怪物: 做法: 用优先队列把怪物能力装进去:能力小放前面: 最重要的是数据量要用读入挂才能过:(读入挂太神奇了!!) Swordsman Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)Total Submission(s): 2049    Acce

2018 Multi-University Training Contest 3

2018 Multi-University Training Contest 2 题解 A - Problem A. Ascending Rating 题目描述:给定一个序列,分别求出所有长度为\(m\)的区间的\(maxrating, count\),对于每个长度为\(m\)的区间,一开始\(maxrating=-1, count=0\),然后从左往右扫,扫到一个大于\(maxrating\)的值时,\(count+1, maxrating=\)那个数. solution 从左往右做,用单调队

2018 Multi-University Training Contest 1 Distinct Values 【贪心 + set】

任意门:http://acm.hdu.edu.cn/showproblem.php?pid=6301 Distinct Values Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 5312    Accepted Submission(s): 1823 Problem Description Chiaki has an array of

2018 Multi-University Training Contest 4 Problem L. Graph Theory Homework 【YY】

传送门:http://acm.hdu.edu.cn/showproblem.php?pid=6343 Problem L. Graph Theory Homework Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others)Total Submission(s): 1536    Accepted Submission(s): 830 Problem Description Ther