2018 Multi-University Training Contest 1

1001 Maximum Multiple

谈学姐写的

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 long long n,i,j,k,s,t,ans,T;
 4 long long a[1000010];
 5 int main()
 6 {
 7         n=1e6;
 8         for (i=1;i<=n;i++)
 9         {
10                 t=-1;
11                 if (i%3==0)
12                 {
13                         s=i/3;
14                         t=s*s;
15                         t=t*s;
16                 }
17                 if (i%4==0)
18                 {
19                         s=i/4;
20                         ans=s*s;
21                         ans=ans*2*s;
22                         if (ans>t) t=ans;
23                 }
24                 if (i%6==0)
25                 {
26                         s=i/6;
27                         ans=s*s*2;
28                         ans=ans*s*3;
29                         if (ans>t) t=ans;
30                 }
31                 a[i]=t;
32         }
33         scanf("%lld",&T);
34         while (T--)
35         {
36                 scanf("%lld",&n);
37                 printf("%lld\n",a[n]);
38         }
39 }
谈学姐

 

1002 Balanced Sequence

瞎比排序

  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 struct sam
  4 {
  5         long long x,y,z;
  6 };
  7 long long n,i,j,k,s,t,ans,T;
  8 sam a[100010];
  9 int b[100010];
 10 char ch;
 11 int cmp(sam &p, sam &q)
 12 {
 13         return (p.x<q.x||(p.x==q.x&&p.y>q.y));
 14 }
 15 int cmp2(sam &p, sam &q)
 16 {
 17         return (p.y>q.y||(p.x>q.x&&p.y==q.y));
 18 }
 19 int main()
 20 {
 21         scanf("%lld",&T);
 22         while (T--)
 23         {
 24                 scanf("%lld",&n);
 25                 ch=getchar();
 26                 ans=0;
 27                 for (i=1;i<=n;i++)
 28                 {
 29                         ch=getchar();
 30                         t=0;
 31                         while (ch!='\n')
 32                         {
 33                                 t++;
 34                                 if (ch=='(') b[t]=0;
 35                                 else
 36                                 {
 37                                         b[t]=1;
 38                                         if (t>=2&&b[t-1]==0)
 39                                         {
 40                                                 t-=2;
 41                                                 ans++;
 42                                         }
 43                                 }
 44                                 ch=getchar();
 45                         }
 46                         s=1;
 47                         while (s<=t&&b[s]==1) s++;
 48                         s--;
 49                         a[i].x=s;a[i].y=t-s;a[i].z=0;
 50                 }
 51                 sort(a+1,a+1+n,cmp);
 52                 s=0;
 53                 for (i=1;i<=n;i++)
 54                 {
 55                         if (a[i].x<a[i].y)
 56                         {
 57                                 if (s>=a[i].x)
 58                                 {
 59                                         ans+=a[i].x;
 60                                         s=s-a[i].x+a[i].y;
 61                                 }
 62                                 else
 63                                 {
 64                                         ans+=s;
 65                                         s=a[i].y;
 66                                 }
 67                                 a[i].z=1;
 68                         }
 69                 }
 70                 for (i=1;i<=n;i++)
 71                 {
 72                         if (a[i].x==a[i].y)
 73                         {
 74                                 if (s>=a[i].x)
 75                                 {
 76                                         ans+=a[i].x;
 77                                 }
 78                                 else
 79                                 {
 80                                         ans+=s;
 81                                         s=a[i].y;
 82                                 }
 83                                 a[i].z=1;
 84                         }
 85                 }
 86                 sort(a+1,a+1+n,cmp2);
 87                 for (i=1;i<=n;i++)
 88                 {
 89                         if (a[i].x>a[i].y)
 90                         {
 91                                 if (s>=a[i].x)
 92                                 {
 93                                         ans+=a[i].x;
 94                                         s=s-a[i].x+a[i].y;
 95                                 }
 96                                 else
 97                                 {
 98                                         ans+=s;
 99                                         s=a[i].y;
100                                 }
101                                 a[i].z=1;
102                         }
103                 }
104                 ans*=2;
105                 printf("%lld\n",ans);
106         }
107 }
谈学姐

 

1003 Triangle Partition

谈学姐写的

#include<bits/stdc++.h>
using namespace std;
struct sam
{
        long long x,y,z;
};
long long n,i,j,k,s,t,ans,T;
sam a[4010];
int cmp(sam &p, sam &q)
{
        return (p.x<q.x);
}
int main()
{
        scanf("%lld",&T);
        while (T--)
        {
                scanf("%lld",&n);
                for (i=1;i<=3*n;i++)
                {
                        scanf("%lld%lld",&a[i].x,&a[i].y);
                        a[i].z=i;
                }
                sort(a+1,a+1+3*n,cmp);
                t=0;
                for (i=1;i<=n;i++)
                {
                        printf("%lld %lld %lld\n",a[t+1].z,a[t+2].z,a[t+3].z);
                        t+=3;
                }
        }
}
谈学姐

 

1004 Distinct Values

区间排序后从前往后扫的时候把前面不属于本区间的暴力删掉用set维护没用过的值

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 const int maxn = 1e5 + 10;
 4 int a[maxn], b[maxn];
 5 typedef pair<int, int> pii;
 6 vector<pii> v;
 7 set<int> NOT, USED;
 8 set<int> :: iterator it;
 9 
10 int main() {
11     int T;
12     scanf("%d", &T);
13     while(T--) {
14         int n, m;
15         scanf("%d %d", &n, &m);
16         NOT.clear(), USED.clear();
17         for(int i = 1; i <= n; ++i) b[i] = 0, NOT.insert(i);
18         v.clear();
19         for(int i = 1; i <= m; ++i) {
20             int l, r;
21             scanf("%d %d", &l, &r);
22             v.push_back(pii(l, r));
23         }
24         sort(v.begin(), v.end());
25         int lst = 1, p = 1;
26         for(int i = 0; i < m; ++i) {
27             int l = v[i].first, r = v[i].second;
28             while (lst < l) {
29                 if(USED.find(b[lst]) != USED.end()) USED.erase(b[lst]), NOT.insert(b[lst]);
30                 lst++;
31             }
32             p = max(p, l);
33             while(p <= r) {
34                 it = NOT.begin();
35                 b[p++] = *it;
36                 NOT.erase(b[p-1]);
37                 USED.insert(b[p-1]);
38             }
39         }
40         for(int i = 1; i <= n; ++i) if(!b[i]) b[i] = 1;
41         for(int i = 1; i <= n; ++i) printf("%d%c", b[i], i == n ? '\n' : ' ');
42     }
43     return 0;
44 }
Aguin

 

1005 Maximum Weighted Matching

按边打牌,用f[u][v]表示两端取/不取的最大值,g[u][v]表示对应的方案数

首先把所有重边合并,然后每次选择一个度为2的点将两条串联的边合并

由于一开始把重边都去了,这时合并两条串联边的时候可能会出现至多一条边和它并联,例如考虑一个三元环的情况,这时把两条并联边也合并

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 typedef long long LL;
 4 const LL mod = 1e9 + 7;
 5 const int maxn = 1e5 + 10;
 6 
 7 struct e {
 8     int u, v;
 9     LL f[2][2], g[2][2];
10     e(int U = -1, int V = -1, int W = -1) {
11         u = U, v = V, memset(f, -1, sizeof(f)); memset(g, 0, sizeof(g));
12         if(W != -1) f[0][0] = 0, f[1][1] = W, g[0][0] = g[1][1] = 1;
13     }
14     bool operator < (const e & o) const {return v < o.v;}
15 };
16 set<e> G[maxn];
17 
18 inline void ud(LL & f, LL & g, LL nf, LL ng) {
19     if(nf > f) f = nf, g = ng;
20     else if(nf == f) g = (g + ng) % mod;
21 }
22 
23 queue<int> q;
24 int main() {
25     int T;
26     scanf("%d", &T);
27     while(T--) {
28         int n, m, y = -1;
29         scanf("%d %d", &n, &m);
30         for(int i = 1; i <= n; ++i) G[i].clear();
31         for(int i = 1; i <= m; ++i) {
32             int u, v, w;
33             scanf("%d %d %d", &u, &v, &w);
34             set<e> :: iterator it = G[u].find(e(0, v));
35             if(it == G[u].end()) G[u].insert(e(u, v, w)), G[v].insert(e(v, u, w));
36             else if((*it).f[1][1] == w) {
37                 e t = *it; t.g[1][1]++; G[u].erase(t); G[u].insert(t);
38                 t = *(G[v].find(e(0, u))); t.g[1][1]++; G[v].erase(t); G[v].insert(t);
39             }
40             else if((*it).f[1][1] < w){
41                 e t = *it; t.f[1][1] = w; t.g[1][1] = 1; G[u].erase(t); G[u].insert(t);
42                 t = *(G[v].find(e(0, u))); t.f[1][1] = w; t.g[1][1] = 1; G[v].erase(t); G[v].insert(t);
43             }
44         }
45         while(!q.empty()) q.pop();
46         for(int i = 1; i <= n; ++i) if(G[i].size() <= 2) q.push(i);
47         while(!q.empty()) {
48             int x = q.front(); q.pop();
49             if(G[x].size() == 1) {y = x; continue;}
50             e a = *G[x].begin(), b = *G[x].rbegin(), c(a.v, b.v); G[x].clear();
51             G[a.v].erase(e(0, x)), G[b.v].erase(e(0, x));
52             for(int ua = 0; ua <= 1; ++ua) for(int va = 0; va <= 1; ++va)
53                 for(int ub = 0; ua + ub <= 1; ++ub) for(int vb = 0; vb <= 1; ++vb)
54                     if(a.f[ua][va] == -1 || b.f[ub][vb] == -1) continue;
55                     else ud(c.f[va][vb], c.g[va][vb], a.f[ua][va] + b.f[ub][vb], a.g[ua][va] * b.g[ub][vb] % mod);
56             if(G[a.v].find(e(0, b.v)) != G[a.v].end()) {
57                 e d = *G[a.v].find(e(0, b.v)), f = e(a.v, b.v);
58                 G[a.v].erase(e(0, b.v)), G[b.v].erase(e(0, a.v));
59                 if(G[a.v].size() == 1) q.push(a.v);
60                 if(G[b.v].size() == 1) q.push(b.v);
61                 for(int ua = 0; ua <= 1; ++ua) for(int va = 0; va <= 1; ++va)
62                     for(int ub = 0; ua + ub <= 1; ++ub) for(int vb = 0; va + vb <= 1; ++vb)
63                         if(c.f[ua][va] == -1 || d.f[ub][vb] == -1) continue;
64                         else ud(f.f[ua + ub][va + vb], f.g[ua + ub][va + vb], c.f[ua][va] + d.f[ub][vb], c.g[ua][va] * d.g[ub][vb] % mod);
65                 c = f;
66             }
67             G[a.v].insert(c);
68             swap(c.u, c.v), swap(c.f[1][0], c.f[0][1]), swap(c.g[1][0], c.g[0][1]);
69             G[b.v].insert(c);
70         }
71         e a = *G[y].begin();
72         LL ans1 = -1, ans2 = 0;
73         for(int ua = 0; ua <= 1; ++ua) for(int va = 0; va <= 1; ++va)
74             if(a.f[ua][va] != -1) ud(ans1, ans2, a.f[ua][va], a.g[ua][va]);
75         printf("%lld %lld\n", ans1, ans2);
76     }
77     return 0;
78 }
Aguin

 

1006 Period Sequence

杜老师教的做法~

问题等价于求$(x, i, j)$三元组满足$s[i] = s[j] = x$

若$i = j$,贡献是$(i - a + 1)(b - i + 1)$,若$i < j$,贡献是$(i - a + 1)(b - j + 1)$,$i > j$和前面一样直接乘二就好

考虑$i = j$的情况,首先枚举每个余数$r$,把$0$至$n - 1$中每个余$r$的项抠出来,记这些位置为$pos$,每个位置对应着一个等差数列

对于每个位置对应的等差数列,找到它为$r$的那一项在原数列$S$中的位置,并记这个位置为这个等差数列的第$0$项

那么这个等差数列的每一项在原数列中的位置都是它在自己所在的等差数列中的位置的一次函数,而等差数列本身就是一次函数

于是所要求的贡献其实是一个三次函数的前缀和,也就是四次函数,求个前五项,用拉格朗日插出来,然后找到$[a, b]$对应等差数列中项数的位置,减一减

对于$i < j$的情况,枚举两个等差数列,只有当他们相同的项同时在$[a, b]$中间才有贡献,同样是四次函数

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 typedef long long LL;
 4 const LL mod = 1e9 + 7;
 5 LL L[2222], R[2222];
 6 int s[2222];
 7 
 8 // length, f[1, ..., n], f[x]
 9 LL inv_fac[2222], pre[2222], suf[2222];
10 LL Lagrange(int n, LL *fx, LL x) {
11     if(1 <= x && x <= n) return fx[x];
12     inv_fac[0] = inv_fac[1] = 1;
13     for(int i = 2; i <= n; ++i) inv_fac[i] = inv_fac[mod % i] * (mod - mod / i) % mod;
14     for(int i = 3; i <= n; ++i) inv_fac[i] = inv_fac[i - 1] * inv_fac[i] % mod;
15     pre[0] = suf[n + 1] = 1;
16     for(int i = 1; i <= n; ++i) pre[i] = pre[i - 1] * (x % mod + mod + mod - i) % mod;
17     for(int i = n; i >= 1; --i) suf[i] = suf[i + 1] * (x % mod + mod + mod - i) % mod;
18     LL ret = 0;
19     for(int i = 1; i <= n; ++i) {
20         LL t = pre[i - 1] * suf[i + 1] % mod * inv_fac[i - 1] % mod * inv_fac[n - i] % mod;
21         if((n - i) % 2) t = t * (mod - 1) % mod;
22         ret = (ret + t * fx[i]) % mod;
23     }
24     return ret;
25 }
26 
27 int main() {
28     int T;
29     scanf("%d", &T);
30     while(T--) {
31         int n;
32         LL a, b, ans = 0;
33         scanf("%d %lld %lld", &n, &a, &b);
34         for(int i = 0; i < n; ++i) scanf("%d", s + i);
35         for(int r = 0; r < n; ++r) {
36             vector<int> pos;
37             for(int i = 0; i < n; ++i)
38                 if(s[i] % n == r) pos.push_back(i - s[i] + r);
39             sort(pos.begin(), pos.end());
40             for(int i = 0; i < pos.size(); ++i) {
41                 LL sum = 0, fx[6];
42                 L[i] = (a - pos[i] + n - 1) / n;
43                 while(pos[i] + n * L[i] < a) L[i]++;
44                 while(pos[i] + n * (L[i] - 1) >= a) L[i]--;
45                 R[i] = (b - pos[i]) / n;
46                 while(pos[i] + n * (R[i] + 1) <= b) R[i]++;
47                 while(pos[i] + n * R[i] > b) R[i]--;
48                 for(int k = 0; k < 5; ++k) {
49                     sum = (sum + (r + k * n) * (pos[i] + k * n + mod - a % mod + mod + 1) % mod * (b % mod - pos[i] - k * n + mod + 1)) % mod;
50                     fx[k + 1] = sum;
51                 }
52                 ans = (ans + Lagrange(5, fx, R[i] + 1) - Lagrange(5, fx, L[i]) + mod) % mod;
53             }
54             for(int i = 0; i < pos.size(); ++i) {
55                 for(int j = i + 1; j < pos.size(); ++j) {
56                     LL ml = max(L[i], L[j]), mr = min(R[i], R[j]);
57                     if(ml > mr) continue;
58                     LL sum = 0, fx[6];
59                     for(int k = 0; k < 5; ++k) {
60                         sum = (sum + (r + k * n) * (pos[i] + k * n + mod - a % mod + mod + 1) % mod * (b % mod - pos[j] - k * n + mod + 1)) % mod;
61                         fx[k + 1] = sum;
62                     }
63                     ans = (ans + 2 * (Lagrange(5, fx, mr + 1) - Lagrange(5, fx, ml) + mod)) % mod;
64                 }
65             }
66         }
67         printf("%lld\n", ans);
68     }
69     return 0;
70 }
Aguin

 

1007 Chiaki Sequence Revisited

谈学姐写的

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 struct sam
 4 {
 5         long long x,y,z;
 6 };
 7 long long n,i,j,k,s,t,ans,T,l,r,x,mid,temp,temp2,ni,mod=1e9+7,temp3;
 8 long long a[100010];
 9 int main()
10 {
11         scanf("%lld",&T);
12         ni=(1+mod)/2;
13 
14         while (T--)
15         {
16                 scanf("%lld",&n);
17                 if (n<=2)
18                 {
19                         printf("%lld\n",n);
20                         continue;
21                 }
22                 ans=1;n--;
23                 l=2;r=n;x=0;
24                 while (l<=r)
25                 {
26                         mid=(l+r)/2;
27                         s=0;t=mid;
28                         while (t>0)
29                         {
30                                 s+=t;
31                                 t=t/2;
32                         }
33                         if (s>=n)
34                         {
35                                 x=mid;
36                                 r=mid-1;
37                         } else l=mid+1;
38                 }
39                 t=x-1;
40                 s=0;
41                 while (t>0)
42                 {
43                         s+=t;
44                         t=t/2;
45                 }
46                 t=x-1;temp3=1;
47                 while (t>0)
48                 {
49                         temp=(1+t)%mod;
50                         temp2=t%mod;
51                         temp=temp*temp2%mod;
52                         temp=temp*ni%mod;
53                         temp=temp*temp3%mod;
54                         ans=(ans+temp)%mod;
55                         t=t/2;
56                         temp3=temp3*2%mod;
57                 }
58                 temp=(n-s)%mod;
59                 x=x%mod;
60                 temp=temp*x%mod;
61                 ans=(ans+temp)%mod;
62                 while (ans<0) ans+=mod;
63                 printf("%lld\n",ans);
64         }
65 }
谈学姐

 

1008 RMQ Similar Sequence

比赛的时候没有发现跨过最大值两边就没影响了……

建笛卡尔树的时候实际上单调栈维护的是最右的一条链

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 typedef long long LL;
 4 const LL mod = 1e9 + 7;
 5 const int maxn = 1e6 + 10;
 6 int a[maxn], st[maxn], ls[maxn], rs[maxn], vis[maxn];
 7 LL ans, inv[maxn];
 8 
 9 int sz[maxn];
10 void dfs(int x) {
11     sz[x] = 1;
12     if(ls[x]) dfs(ls[x]), sz[x] += sz[ls[x]];
13     if(rs[x]) dfs(rs[x]), sz[x] += sz[rs[x]];
14     ans = ans * inv[sz[x]] % mod;
15 }
16 
17 int main() {
18     inv[1] = 1;
19     for(int i = 2; i < maxn; ++i) inv[i] = inv[mod % i] * (mod - mod / i) % mod;
20     int T;
21     scanf("%d", &T);
22     while(T--) {
23         int n, p = 0;
24         scanf("%d", &n);
25         for(int i = 1; i <= n; ++i) ls[i] = rs[i] = vis[i] = 0;
26         for(int i = 1; i <= n; ++i) {
27             scanf("%d", a + i);
28             int pop = 0;
29             while(p && a[st[p]] < a[i]) pop = 1, p--;
30             if(p) rs[st[p]] = i;
31             if(pop) ls[i] = st[p+1];
32             st[++p] = i;
33         }
34         for(int i = 1; i <= n; ++i) vis[ls[i]] = vis[rs[i]] = 1;
35         for(int i = 1; i <= n; ++i) if(!vis[i]) ans = 1, dfs(i);
36         printf("%lld\n", ans * n % mod * inv[2] % mod);
37     }
38     return 0;
39 }
Aguin

 

1009 Lyndon Substring

论文不学

 

1010 Turn Off The Light

$f[i][0/1]$表示$1$至$i - 1$全为$0$,$i$的状态为$0/1$,$i + 1$至$n$为原串, 从$i$开始往右关完的最少步
$g[i]$表示从$i$出发把左边关完回到i的最少步,$h[i]$表示从i出发把左边关完回到$i$后位置$i$的$0/1$状态
终点可能是最右边的灯位置$l$或者往左一个位置$l - 1$

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 typedef long long LL;
 4 const LL mod = 1e9 + 7;
 5 const int maxn = 1e6 + 10;
 6 const int INF = 1e9;
 7 int f[maxn][2], g[maxn], h[maxn];
 8 int n, b[maxn], z[maxn];
 9 char s[maxn];
10 
11 void solve() {
12     int l = n + 1, r = 0;
13     for(int i = 1; i <= n; ++i) if(b[i]) l = min(l, i), r = max(r, i);
14     if(l > r) {
15         for(int i = 1; i <= n; ++i) z[i] = 0;
16         return;
17     }
18     f[r][0] = 0, f[r][1] = 3;
19     if(1 < r) f[r - 1][0] = 1, f[r - 1][1] = 2;
20     for(int i = r - 2; i >= 1; --i) {
21         f[i][0] = f[i + 1][b[i + 1] ^ 1] + 1;
22         f[i][1] = f[i + 1][b[i + 1]] + 3;
23     }
24     g[l + 1] = 2, h[l + 1] = b[l + 1] ^ 1;
25     for(int i = l + 2; i <= r; ++i) {
26         if(h[i - 1]) g[i] = g[i - 1] + 2, h[i] = b[i] ^ 1;
27         else g[i] = g[i - 1] + 4, h[i] = b[i];
28     }
29     for(int i = 1; i <= l; ++i) z[i] = min(z[i], f[i][b[i]]);
30     for(int i = l + 1; i <= r; ++i) z[i] = min(z[i], g[i] + f[i][h[i]]);
31 }
32 
33 int main() {
34     int T;
35     scanf("%d", &T);
36     while(T--) {
37         scanf("%d %s", &n, s + 1);
38         for(int i = 1; i <= n; ++i) b[i] = s[i] - '0', z[i] = INF;
39         solve();
40         reverse(b + 1, b + 1 + n), reverse(z + 1, z + 1 + n);
41         solve();
42         reverse(z + 1, z + 1 + n);
43         LL ans = 0;
44         for(int i = 1; i <= n; ++i) ans = (ans + (LL) i * z[i]) % mod;
45         printf("%lld\n", ans);
46     }
47     return 0;
48 }
Aguin

 

1011 Time Zone

沙雕题还WA一发

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 int main() {
 5     int N;
 6     scanf("%d", &N);
 7     while(N--) {
 8         int h, m;
 9         char s[11];
10         scanf("%d %d %s", &h, &m, s);
11         int l = strlen(s), dh, dm;
12         if(l == 5) {
13             if(s[3] == '+') dh = 8 - (s[4] - '0'), dm = 0;
14             else dh = 8 + (s[4] - '0'), dm = 0;
15         }
16         else if(l == 6) {
17             if(s[3] == '+') dh = 8 - ((s[4] - '0') * 10 + (s[5] - '0')), dm = 0;
18             else dh = 8 + ((s[4] - '0') * 10 + (s[5] - '0')), dm = 0;
19         }
20         else if(l == 7) {
21             if(s[3] == '+') dh = 8 - (s[4] - '0'), dm = -6 * (s[6] - '0');
22             else dh = 8 + (s[4] - '0'), dm = 6 * (s[6] - '0');
23         }
24         else {
25             if(s[3] == '+') dh = 8 - ((s[4] - '0') * 10 + (s[5] - '0')), dm = -6 * (s[7] - '0');
26             else dh = 8 + ((s[4] - '0') * 10 + (s[5] - '0')), dm = 6 * (s[7] - '0');
27         }
28         h -= dh, m -= dm;
29         while(m >= 60) m -= 60, h++;
30         while(m < 0) m += 60, h--;
31         while(h >= 24) h -= 24;
32         while(h < 0) h += 24;
33         printf("%02d:%02d\n", h, m);
34     }
35     return 0;
36 }
Aguin

 

posted @ 2018-07-25 10:14  Aguin  阅读(316)  评论(0编辑  收藏  举报