牛客多校7
A
队友写的。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
//#pragma comment(linker, "/stack:200000000") //#pragma GCC optimize("Ofast,no-stack-protector") //#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native") //#pragma GCC optimize("unroll-loops") #include<bits/stdc++.h> #define fi first #define se second #define mp make_pair #define pb push_back #define pi acos(-1.0) #define ll long long #define vi vector<int> #define mod 1000000007 #define ld long double #define C 0.5772156649 #define ls l,m,rt<<1 #define rs m+1,r,rt<<1|1 #define pll pair<ll,ll> #define pil pair<int,ll> #define pli pair<ll,int> #define pii pair<int,int> #define cd complex<double> #define ull unsigned long long #define base 1000000000000000000 #define Max(a,b) ((a)>(b)?(a):(b)) #define Min(a,b) ((a)<(b)?(a):(b)) #define fio ios::sync_with_stdio(false);cin.tie(0) template<typename T> inline T const& MAX(T const &a,T const &b){return a>b?a:b;} template<typename T> inline T const& MIN(T const &a,T const &b){return a<b?a:b;} inline void add(ll &a,ll b){a+=b;if(a>=mod)a-=mod;} inline void sub(ll &a,ll b){a-=b;if(a<0)a+=mod;} inline ll gcd(ll a,ll b){return b?gcd(b,a%b):a;} inline ll qp(ll a,ll b){ll ans=1;while(b){if(b&1)ans=ans*a%mod;a=a*a%mod,b>>=1;}return ans;} inline ll qp(ll a,ll b,ll c){ll ans=1;while(b){if(b&1)ans=ans*a%c;a=a*a%c,b>>=1;}return ans;} using namespace std; const double eps=1e-8; const ll INF=0x3f3f3f3f3f3f3f3f; const int N=500000+10,maxn=4000000+10,inf=0x3f3f3f3f; int ans[N]; int main() { int n; scanf("%d",&n); int s=n-1; while(s>0) { int len; for(int i=20;i>=0;i--) { if((s>>i)&1) { len=i+1; break; } } int te=s^((1<<len)-1); for(int i=te,j=s;i<=s;j--,i++) ans[i]=j; s=te-1; } for(int i=0;i<n;i++) printf("%d ",ans[i]); puts(""); return 0; } /******************** ********************/
J
每个点最多向右延伸51个,向下延伸51个,枚举矩阵的左上角,再枚举向右延伸的边有多长,向下延伸的边是单调的
所以复杂度为n * n * 52
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<bits/stdc++.h> #define LL long long #define fi first #define se second #define mk make_pair #define pii pair<int, int> #define y1 skldjfskldjg #define y2 skldfjsklejg using namespace std; const int N = 1000 + 7; const int M = 1e5 + 7; const int inf = 0x3f3f3f3f; const LL INF = 0x3f3f3f3f3f3f3f3f; const int mod = 1e9 +7; int n, m, a[N][N], r[N][N], d[N][N], cnt[55]; char s[N][N]; int main() { scanf("%d%d", &n, &m); for(int i = 1; i <= n; i++) scanf("%s", s[i] + 1); for(int i = 1; i <= n; i++) { for(int j = 1; j <= m; j++) { if(s[i][j] >= 'a' && s[i][j] <= 'z') { a[i][j] = s[i][j] - 'a'; } else { a[i][j] = s[i][j] - 'A' + 26; } } } for(int i = 1; i <= n; i++) { int pos = 1; memset(cnt, 0, sizeof(cnt)); for(int j = 1; j <= m; j++) { while(pos <= m && !cnt[a[i][pos]]) cnt[a[i][pos++]]++; r[i][j] = pos - j; cnt[a[i][j]]--; } } for(int j = 1; j <= m; j++) { int pos = 1; memset(cnt ,0, sizeof(cnt)); for(int i = 1; i <= n; i++) { while(pos <= n && !cnt[a[pos][j]]) cnt[a[pos++][j]]++; d[i][j] = pos - i; cnt[a[i][j]]--; } } LL ans = 0; for(int i = 1; i <= n; i++) { for(int j = 1; j <= m; j++) { int R = r[i][j], D = d[i][j]; memset(cnt, 0, sizeof(cnt)); int mn = inf; for(int k = 1; k <= D; k++) { cnt[r[i + k - 1][j]]++; mn = min(mn, r[i + k - 1][j]); } ans += D; for(int k = 2; k <= R; k++) { while(D > d[i][j + k - 1]) { cnt[r[i + D - 1][j]]--; D--; } while(!cnt[mn]) mn++; while(mn < k) { cnt[r[i + D - 1][j]]--; D--; while(!cnt[mn]) mn++; } ans += D; } } } printf("%lld\n", ans); return 0; } /* */
E
我们会发现贪心的构造点的数量不够,所以我们用背包使他获得更好的利用。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<bits/stdc++.h> #define LL long long #define fi first #define se second #define mk make_pair #define pii pair<int, int> #define y1 skldjfskldjg #define y2 skldfjsklejg using namespace std; const int N = 1e6 + 7; const int M = 1e5 + 7; const int inf = 0x3f3f3f3f; const LL INF = 0x3f3f3f3f3f3f3f3f; const int mod = 1e9 +7; int comb(int n) { return n * (n - 1) * (n - 2) * (n - 3) / 4 / 3 / 2; } int comb2(int n) { return n * (n - 1) * (n - 2) / 3 / 2; } int dp[1000001]; int fa[1000001]; int num[1000001]; int cnt[100]; int cnt2[100]; int k, n, m; vector<pii>ans; int main() { // freopen("a.txt", "w", stdout); for(int i = 4; i <= 75; i++) cnt[i] = comb(i); for(int i = 3; i <= 75; i++) cnt2[i] = comb2(i); n = 63; memset(dp, inf, sizeof(dp)); dp[cnt[n]] = 0; int mx = cnt[n]; for(int i = cnt[n]; i < 1000000; i++) { for(int j = 3; j <= n; j++) { if(i + cnt2[j] > 1000000) continue; if(dp[i] + 1 < dp[i + cnt2[j]]) { dp[i + cnt2[j]] = dp[i] + 1; fa[i + cnt2[j]] = i; num[i + cnt2[j]] = j; } } if(dp[i] > dp[mx]) mx = i; } // cout << mx << endl; scanf("%d", &k); if(k <= cnt[n]) { for(int i=70;i>=4;i--) { if(cnt[i]<=k) { k-=cnt[i]; n=i; break; } } for(int i=1;i<=n;i++) for(int j=i+1;j<=n;j++) ans.push_back(mk(i,j)); int res=0; for(int i=70;i>=3;i--) { int te=i*(i-1)*(i-2)/3/2; while(te<=k&&i<=n) { res++; for(int j=1;j<=i;j++) ans.push_back(mk(res+n,j)); k-=te; } } n+=res; } else { for(int i = 1; i <= n; i++) for(int j = i + 1; j <= n; j++) ans.push_back(mk(i, j)); int tot = n + 1; int all = cnt[n]; while(k != cnt[n]) { for(int i = 1; i <= num[k]; i++) ans.push_back(mk(tot, i)); all += cnt[num[k]]; k = fa[k]; tot++; } n = tot - 1; } printf("%d %d\n", n, ans.size()); for(int i = 0; i < ans.size(); i++) printf("%d %d\n", ans[i].fi, ans[i].se); return 0; } /* */