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 ",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!=' ') 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 ",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 ",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 ? ' ' : ' '); 42 } 43 return 0; 44 }
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 ", ans1, ans2); 76 } 77 return 0; 78 }
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 ", ans); 68 } 69 return 0; 70 }
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); 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 ",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 ", ans * n % mod * inv[2] % mod); 37 } 38 return 0; 39 }
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 ", ans); 46 } 47 return 0; 48 }
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 ", h, m); 34 } 35 return 0; 36 }