2018 Multi-University Training Contest 8

1001:HDU6397 Character Encoding

公式题,可以用容斥和隔板法推出来。

 

#include <iostream>
#include <cstdio>
#include <cstdlib>
using namespace std;
const int MAX=3e5+5;
const long long mod=998244353;
long long fac[MAX],rev[MAX];
long long qp(long long p,long long q)
{
    int cnt=1;
    while(q>0)
    {
        if(q%2==1) cnt=(cnt*p)%mod;
        q/=2;
        p=(p*p)%mod;
    }
    return cnt%mod;
}

long long C(long long a,long long b)
{
    if(a<0||b<0) return 0;
    long long flag=fac[a];
    return ((fac[a]*rev[b])%mod*rev[a-b])%mod;
}

long long n,m,k;

long long solve(long long sum,long long num,long long p)
{
    if(sum==0) return 1;
    long long cnt=0;
    int i,j;
    for(i=0;i<=num;i++)
    {
        long long a=C(num,i),b=C(sum-p*i-i+num-1,sum-p*i-i);
        long long flag=(C(num,i)*C(sum-p*i-i+num-1,sum-p*i-i))%mod;
        if(i%2==1) flag=(mod-flag)%mod;
        cnt=(cnt+flag)%mod;
    }
    return cnt;
}

int main()
{
    int i,j;
    int t;
    scanf("%d",&t);
        fac[0]=1;
    rev[0]=1;
    for(i=1;i<MAX;i++)
    {
        fac[i]=(fac[i-1]*i)%mod;
        rev[i]=qp(fac[i],mod-2);
    }
    while(t--){
        scanf("%lld%lld%lld",&n,&m,&k);
        long long ans=solve(k,m,n-1);
        printf("%lld\n",ans);
    }

    return 0;
}
View Code

1002:HDU6398 Pizza Hub

 

1004:HDU6340 Parentheses Matrix

 构造题,思路被限制了,不应该把所有行或列填满,牺牲两行可以填满更多的列。

#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=200+5;
int t,n,m;
char mp[205][205];
int flag;

void solve(){
    int i,j;
    flag=0;
    if(n%2){
        for(i=0;i<n;i++){
            for(j=0;j<m/2;j++)
                mp[i][j]='(';
            for(j=m/2;j<m;j++)
                mp[i][j]=')';
            }
        return ;
    }
    if(m%2){
        for(i=0;i<m;i++){
            for(j=0;j<n/2;j++)
                mp[j][i]='(';
            for(j=n/2;j<n;j++)
                mp[j][i]=')';
            }
        return ;
    }
    if(n<m){
        swap(n,m);
        flag=1;
    }
    if(m>=6){
        for(i=1;i<n-1;i++){
            mp[i][0]='(';
            mp[i][m-1]=')';
        }
        for(i=1;i<n-1;i+=2){
            for(j=1;j<m-1;j++){
                if(j%2==1) mp[i][j]='(';
                else mp[i][j]=')';
            }
            mp[i][0]='(';mp[i][m-1]=')';
        }
        for(i=2;i<n-1;i+=2){
            for(j=1;j<m-1;j++){
                if(j%2==0) mp[i][j]='(';
                else mp[i][j]=')';
            }
        }
        for(i=0;i<m;i++) mp[0][i]='(';
        for(i=0;i<m;i++) mp[n-1][i]=')';
        return ;
    }
    
    
    if(m%3==0){
        for(i=0;i<n/2;i++){
            for(j=0;j<m/6;j++){
                mp[i][j*2]='(';
                mp[i][j*2+1]=')';
            }
            for(j=m/3;j<m*2/3;j++)
                mp[i][j]='(';
            for(j=2*m/3;j<m;j++)
                mp[i][j]=')';
        }
        for(i=n/2;i<n;i++){
            for(j=0;j<m/3;j++)
                mp[i][j]='(';
            for(j=m/3;j<2*m/3;j++)
                mp[i][j]=')';
            for(j=m/3;j<m/2;j++){
                mp[i][j*2]='(';
                mp[i][j*2+1]=')';
            }
        }
    }
    else if((m-4)%3==0){
        m-=4;
        for(i=0;i<n/2;i++){
            for(j=0;j<m/6;j++){
                mp[i][j*2]='(';
                mp[i][j*2+1]=')';
            }
            for(j=m/3;j<m*2/3;j++)
                mp[i][j]='(';
            for(j=2*m/3;j<m;j++)
                mp[i][j]=')';
        }
        for(i=n/2;i<n;i++){
            for(j=0;j<m/3;j++)
                mp[i][j]='(';
            for(j=m/3;j<2*m/3;j++)
                mp[i][j]=')';
            for(j=m/3;j<m/2;j++){
                mp[i][j*2]='(';
                mp[i][j*2+1]=')';
            }
        }
        m+=4;
        for(i=0;i<n/2;i++){
            mp[i][m-4]='(';mp[i][m-3]='(';mp[i][m-2]=')';mp[i][m-1]=')';
        }
        for(i=n/2;i<n;i++){
            mp[i][m-4]='(';mp[i][m-3]=')';mp[i][m-2]='(';mp[i][m-1]=')';
        }
    }
    else{
        m=m-2;
        for(i=0;i<n/2;i++){
            for(j=0;j<m/6;j++){
                mp[i][j*2]='(';
                mp[i][j*2+1]=')';
            }
            for(j=m/3;j<m*2/3;j++)
                mp[i][j]='(';
            for(j=2*m/3;j<m;j++)
                mp[i][j]=')';
        }
        for(i=n/2;i<n;i++){
            for(j=0;j<m/3;j++)
                mp[i][j]='(';
            for(j=m/3;j<2*m/3;j++)
                mp[i][j]=')';
            for(j=m/3;j<m/2;j++){
                mp[i][j*2]='(';
                mp[i][j*2+1]=')';
            }
        }
        m=m+2;
        for(i=0;i<n;i++){
            mp[i][m-2]='(';
            mp[i][m-1]=')';
        }
    }
}

int main(){
    int i,j;
    
    scanf("%d",&t);
    //freopen("1.out","w",stdout);
    while(t--){
        scanf("%d%d",&n,&m);
        solve();
        if(flag){
            for(i=0;i<m;i++){
                for(j=0;j<n;j++)
                    printf("%c",mp[j][i]);
                puts("");
            }
        }
        else{
            for(i=0;i<n;i++){
                for(j=0;j<m;j++)
                    printf("%c",mp[i][j]);
                puts("");
            }
        }
    }
    
    return 0;
}
View Code

 

1005:HDI6401 Magic Square

 简单模拟。

#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=10+5;
int t,n;
char mp[10][10];

void solve(char a,char b){
    int x,y;
    if(a=='1') x=0,y=0;
    else if(a=='2') x=0,y=1;
    else if(a=='3') x=1,y=0;
    else x=1,y=1; 
    if(b=='C'){
        char tmp=mp[x][y];
        mp[x][y]=mp[x+1][y];
        mp[x+1][y]=mp[x+1][y+1];
        mp[x+1][y+1]=mp[x][y+1];
        mp[x][y+1]=tmp;
    }
    else if(b=='R'){
        char tmp=mp[x][y];
        mp[x][y]=mp[x][y+1];
        mp[x][y+1]=mp[x+1][y+1];
        mp[x+1][y+1]=mp[x+1][y];
        mp[x+1][y]=tmp;
    }
}

int main(){
    int i;
    
    scanf("%d",&t);
    while(t--){
        scanf("%d",&n);
        for(i=0;i<3;i++) scanf("%s",&mp[i]);
        for(i=0;i<n;i++){
            char s[MAX];
            scanf("%s",&s);
            solve(s[0],s[1]);
        }
        for(i=0;i<3;i++) puts(mp[i]);
    }
    
    return 0;
}
View Code

 

1009:HUD6405 Make ZYB Happy

找所有本质不同的子串,把所有串建立广义后缀自动机,再把所有串在自动机上跑一边,更新路过的的结点以及parent链,每个节点只能更新一次,最后把所有结点的right集合区间覆盖,再做两遍前缀和可以O(1)回答。

#include <cstdio>
#include <cstring>
#include <queue>
#include <algorithm>
#include <cmath>
#include <vector>
#include <iostream>
#include <stack>
#include <set>
#include <map>
#include <string> 
#define pi acos(-1.0)
using namespace std;

const int MAX=1e6+5;
const int mod=1e9+7;
struct suffix_automaton{
    string s;
    int son[MAX][26],pre[MAX],step[MAX],last,total,rt[MAX];
   
    inline void push_back(int v){
        step[++total]=v;
    }
    
    void init(){
        total=last=0;
        memset(son,0,sizeof(son));
        memset(pre,0,sizeof(pre));
        memset(step,0,sizeof(step));
        pre[0]=-1;
    }
    
    void Extend(int ch){
        push_back(step[last]+1);
        int p=last,np=total;
        rt[np]++;
        for(;!son[p][ch]&&p!=-1;p=pre[p])
            son[p][ch]=np;
        if(p==-1)
            pre[np]=0;
        else{
            int q=son[p][ch];
            if(step[q]!=step[p]+1){
                push_back(step[p]+1);
                int nq=total;
                memcpy(son[nq],son[q],sizeof(son[q]));
                pre[nq]=pre[q];
                pre[q]=pre[np]=nq;
                rt[nq]=rt[q];
                for(;son[p][ch]==q;p=pre[p])
                    son[p][ch]=nq;
            }
            else
                pre[np]=q;
        }
        last=np;
    }
}suf;

long long quickpow(long long x,long long n){
    if(n==0)
        return 1;
    long long res=quickpow(x*x%mod,n/2);
    if(n%2)
        res=res*x%mod;
    return res;
}
 
int n,m,mxlen;  
string str[MAX];
long long ans[MAX],h[MAX],val[MAX];
int vis[MAX];
long long fac[MAX],inv[MAX],pw;
    
int main(){
    int i,j;
    
    suf.init();
    scanf("%d",&n);
    for(i=0;i<n;i++) cin>>str[i],mxlen=max(mxlen,(int)str[i].size());
    for(i=0;i<n;i++) scanf("%lld",&h[i]);
    pw=1;
    for(i=1;i<=mxlen;i++){
        pw=pw*26%mod;
        fac[i]=(fac[i-1]+pw)%mod;
        inv[i]=quickpow(fac[i],mod-2);
    }
    for(i=0;i<n;i++){  //建立广义sam 两种情况 
        suf.last=0;
        for(j=0;j<str[i].size();j++){
            int np=suf.son[suf.last][str[i][j]-'a'];
            if(np==0||suf.step[np]!=j+1) suf.Extend(str[i][j]-'a');
            else suf.last=np;
        }
    }
    for(i=0;i<n;i++){
        int p=0;
        for(j=0;j<str[i].size();j++){
            p=suf.son[p][str[i][j]-'a'];
            int prep=p;
            while(prep!=-1){
                if(vis[prep]==i+1) break;
                vis[prep]=i+1;
                if(!val[prep]) val[prep]=h[i];
                else val[prep]=val[prep]*h[i]%mod;
                prep=suf.pre[prep];
            }
        }
    } 
    for(i=suf.total;i>=1;i--){
        (ans[suf.step[suf.pre[i]]+1]+=val[i])%mod;
        (ans[suf.step[i]+1]-=val[i])%mod;
    }
    for(i=1;i<=mxlen;i++) ans[i]=(ans[i]+ans[i-1]+mod)%mod;
    for(i=1;i<=mxlen;i++) ans[i]=(ans[i]+ans[i-1]+mod)%mod;
    scanf("%d",&m);
    while(m--){
        int len;
        scanf("%d",&len);
        len=min(len,mxlen);
        printf("%lld\n",ans[len]*inv[len]%mod);
    }
    
    return 0;
}
View Code

 

1010:HDU6406 Taotao Picks Apples

 先求出原数列按要求选得到的答案,记录一下每个位置向前最靠近的那个被选的数是哪一个。然后考虑改变某个位置的值时的能产生怎样的贡献。

 若它改变后比它之前那个被选的数要大,则它能被加入这个上升子序列;若反之,则不能加入这个上升子序列。故产生贡献的前半部分即它之前的被选的原上升子序列的长度,之后需要得到离它最近的一个比它大的数往后能接多少个,这个能用线段树维护dp出来答案。

  1 #include<cstdio>
  2 #include<cstdlib>
  3 #include<cstring>
  4 #include<algorithm>
  5 
  6 #define maxn 200000+5
  7 #define inf 0x3f3f3f3f
  8 
  9 using namespace std;
 10 
 11 struct Data{
 12     int x,v,pos;
 13     bool operator <(const Data &T)const{
 14         return x<T.x;
 15     }
 16 }q[maxn];
 17 
 18 struct Seg_Tree {
 19     int l, r;
 20     int mn;
 21 }tr[maxn << 2];
 22 
 23 int tmp[maxn],h[maxn],ans[maxn],dp[maxn],nlst[maxn],lstsum[maxn];
 24 int n,m,cnt,tot;
 25 
 26 namespace fastIO {
 27     #define BUF_SIZE 100000
 28     bool IOerror = 0;
 29     inline char nc() {
 30         static char buf[BUF_SIZE], *p1 = buf + BUF_SIZE, *pend = buf + BUF_SIZE;
 31         if(p1 == pend) {
 32             p1 = buf;
 33             pend = buf + fread(buf, 1, BUF_SIZE, stdin);
 34             if(pend == p1) {
 35                 IOerror = 1;
 36                 return -1;
 37             }
 38         }
 39         return *p1++;
 40     }
 41     inline bool blank(char ch) {
 42         return ch == ' ' || ch == '\n' || ch == '\r' || ch == '\t';
 43     }
 44     inline int rd(int &x) {
 45         char ch;
 46         while(blank(ch = nc()));
 47         if(IOerror) return -1;
 48         for(x = ch - '0'; (ch = nc()) >= '0' && ch <= '9'; x = x * 10 + ch - '0');
 49         return 1;
 50     }
 51     #undef BUF_SIZE
 52 };
 53 using namespace fastIO;
 54 
 55 void Update(int k){
 56     tr[k].mn = min(tr[k << 1].mn, tr[k << 1 | 1].mn);
 57 }
 58 
 59 void Build(int k, int l, int r){
 60     tr[k].l = l; tr[k].r = r;
 61     if (l == r) {
 62         tr[k].mn=inf;
 63         return;
 64     }
 65     int mid = (l + r) >> 1;
 66     Build(k << 1, l, mid);
 67     Build(k << 1 | 1, mid + 1, r);
 68     Update(k);
 69 }
 70 
 71 void Insert(int k, int pos, int val){
 72     if (tr[k].l == tr[k].r) {
 73         tr[k].mn=val;
 74         return;
 75     }
 76     if (tr[k << 1].r >= pos) Insert(k << 1, pos, val);
 77     else if (tr[k << 1 | 1].l <= pos) Insert(k << 1 | 1, pos, val);
 78     Update(k);
 79 }
 80 
 81 int Query(int k, int l, int r){
 82     if (tr[k].l == l && tr[k].r == r) return tr[k].mn;
 83     if (tr[k << 1].r >= r) return Query(k << 1, l, r);
 84     else if (tr[k << 1 | 1].l <= l) return Query(k << 1 | 1, l, r);
 85     else return min(Query(k << 1, l, tr[k << 1].r) , Query(k << 1 | 1, tr[k << 1 | 1].l, r));
 86 }
 87 
 88 int bsearch(int x){
 89     int l=1,r=tot,res;
 90     while(l<=r){
 91         int mid=(l+r)>>1;
 92         if(tmp[mid]<=x) res=mid,l=mid+1;
 93         else r=mid-1;
 94     }
 95     return res;
 96 }
 97 
 98 int main(){
 99     int T;
100     rd(T);
101     while(T--){
102         rd(n); rd(m); cnt=tot=0;
103         for(int i=1;i<=n;i++){
104             rd(h[i]); tmp[++cnt]=h[i];
105             lstsum[i]=nlst[i]=dp[i]=0;
106         }
107         for(int i=1;i<=m;i++){            
108             rd(q[i].x); rd(q[i].v); q[i].pos=i;
109             tmp[++cnt]=q[i].v; ans[i]=0;
110         }
111         sort(tmp+1,tmp+1+cnt);
112         for(int i=1;i<=cnt;i++)
113             if(tmp[i]!=tmp[i-1]) tmp[++tot]=tmp[i];
114         for(int i=1;i<=m;i++) q[i].v=bsearch(q[i].v);
115         for(int i=1;i<=n;i++) h[i]=bsearch(h[i]);
116         sort(q+1,q+1+m);
117         Build(1,1,tot+1);
118         for(int i=n;i>=1;i--){
119             int t=Query(1,h[i]+1,tot+1);
120             dp[i]=(t==inf?1:dp[t]+1);
121             Insert(1,h[i],i);
122         }
123         int now=0;
124         for(int i=1;i<=n;i++){
125             nlst[i]=now; lstsum[i]=lstsum[i-1];
126             if(h[now]<h[i]) now=i,lstsum[i]++;
127         }
128         Build(1,1,tot+1);
129         int ii=m;
130         for(int j=n;j>=1;j--){        
131             while(q[ii].x>=j && ii>=1){
132                 if(q[ii].v>h[nlst[q[ii].x]]){
133                     int t=Query(1,q[ii].v+1,tot+1);
134                     if(t==inf) ans[q[ii].pos]=lstsum[nlst[q[ii].x]]+1;
135                     else ans[q[ii].pos]=lstsum[nlst[q[ii].x]]+1+dp[t];
136                 }
137                 else{
138                     int t=Query(1,h[nlst[q[ii].x]]+1,tot+1);
139                     if(t==inf) ans[q[ii].pos]=lstsum[nlst[q[ii].x]];
140                     else ans[q[ii].pos]=lstsum[nlst[q[ii].x]]+dp[t];
141                 }    
142                 ii--;                        
143             }
144             Insert(1,h[j],j);
145         }
146         for(int i=1;i<=m;i++)
147             printf("%d\n",ans[i]);
148     }
149     return 0;
150 }
View Code

 

1011:HDU6407  Pop the Balloons

 

1012:HDU6408 From ICPC to ACM

 巧妙的贪心。由于零件的储存没有限制,故可以通过以前每天的信息dp出每天最优的零件价格。接着考虑把每天的产能都拉满,对于第i天取出造价最低的demand[i]个电脑卖掉,之后如果超过今天的储存限制,则丢掉造价较高的超出限制的那些电脑。可以通过multiset维护这些信息。

 1 #include<set>
 2 #include<cstdlib>
 3 #include<cstring>
 4 #include<cstdio>
 5 #include<algorithm>
 6 
 7 #define maxn 50000+5
 8 
 9 using namespace std;
10 
11 typedef long long LL;
12 
13 struct Data {
14     int sum; LL val;
15     Data() {}
16     Data(int x, LL y) { sum = x; val = y; }
17     bool operator <(const Data &T)const {
18         return val<T.val;
19     }
20 };
21 
22 multiset <Data> s;
23 
24 LL sum[maxn], tag;
25 int c[maxn], t[maxn], dem[maxn], m[maxn], p[maxn], cap[maxn], sr[maxn], se[maxn];
26 int n;
27 
28 int main() {
29     int T;
30     scanf("%d", &T);
31     while (T--) {
32         scanf("%d", &n); s.clear();
33         for (int i = 1; i <= n; i++)
34             scanf("%d%d%d%d", &c[i], &dem[i], &m[i], &p[i]);
35         for (int i = 1; i<n; i++)
36             scanf("%d%d%d", &cap[i], &sr[i], &se[i]);
37         for (int i = 1; i<n; i++) sum[i] = sum[i - 1] + sr[i];
38         LL tmp = 0x3f3f3f3f;
39         for (int i = 1; i <= n; i++) {
40             t[i] = min((LL)c[i], sum[i - 1] + tmp);
41             tmp = min(tmp, c[i] - sum[i - 1]);
42         }
43         LL tag = 0, ans = 0, all = 0;
44         bool flag = true;
45         for (int i = 1; i <= n; i++) {
46             int now = dem[i];
47             s.insert(Data ( p[i], m[i] + t[i] - tag )); all += p[i];
48             while (now && !s.empty()) {
49                 set<Data>::iterator it = s.begin();
50                 Data a = (*it);
51                 if (a.sum <= now) {
52                     now -= a.sum; ans += (LL)a.sum*(a.val + tag);
53                     all -= a.sum; s.erase(it);
54                 }
55                 else {
56                     a.sum -= now; ans += (LL)now*(a.val + tag);
57                     all -= now; now = 0; s.erase(it); s.insert(a);
58                 }
59             }
60             if (now) {
61                 flag = false; puts("-1");
62                 break;
63             }
64             while (i!=n && all>cap[i] && !s.empty()) {
65                 set<Data>::iterator it = s.end();
66                 Data a = *(--it);
67                 if (all - a.sum >= cap[i]) {
68                     all -= a.sum; s.erase(it);
69                 }
70                 else {
71                     a.sum -= all - cap[i]; all = cap[i];
72                     s.erase(it); s.insert(a);
73                 }
74             }
75             tag += se[i];
76         }
77         if (flag) printf("%lld\n", ans);
78     }
79     return 0;
80 }
View Code

 

posted @ 2018-08-19 20:38  Hetui  阅读(304)  评论(0编辑  收藏  举报