目录node
\[N^2\text{狂草1e5它不香嘛?}\]
\[\text{By:Unluckierblock}\]ios
题目 1 :
预估成绩 : 60 实际成绩 : 0 考试用时 : 8 : 00 ~ 8 : 50 , 9 : 50 ~ 10 : 10c++
没有什么感受 , 就先写了 暴力30
写完T3以后再来看 T1 , 优化到了60分
测了 大样例的前10组数据, 都没有问题 , 因而就无论了git
然而样例比较独特 , 没有卡掉错误作法 , 最后仍是爆了零大数据
题目 2 :
预估成绩 : 99 实际成绩 : 99 考试用时 : 8 : 50 ~ 9 : 10 , 10 : 15 ~ 10 : 54优化
先写了一发暴力 .
以为暴力过不去大数据 , 就重构代码 , 写了一发线段树
手比较顺 , 很快调了出来 , 没有问题 , 过了大样例ui
题目 3 :
预估成绩 : 40 实际成绩 : 70 考试用时 : 9 : 10 ~ 9 : 47spa
发现了比较优美的性质 , 写了搜索
很快写完以后 过了大样例code
T1:递归
60 % 数据 :
预处理 1 ~ 10000内 全部数的约数
对于每个N, \(O(n ^ 2)\) 枚举其两个约数 L, W
并计算出H = N - L - W.
若H是否也为N的约数 , 则枚举的L, W, H为合法的三元组 , 对此类合法三元组统计答案便可
100 %数据 :
对计算式进行转化 :
L + W + H = N
因为 L, W, H都为 N的约数, 则有:
\(\frac{1}{k1} * N + \frac{1}{k2} * N + \frac{1}{k3} * N = N\)
则有 : \((\frac{1}{k1} + \frac{1}{k2} +\frac{1}{k3}) = 1\)
能够发现, 对于k1, k2, k3的取值, 只有下列三种状况:
能够发现, 对于一个 N , 知足状况1, 必然知足状况2
且状况2的贡献更大 显然状况2更优
则只需考虑 N是否为 3或4 的倍数便可
若N为3的倍数 ,因为状况2的贡献较大 , 则答案即为 \(\frac{N}{3} * \frac{N}{3} * \frac{N}{3} = \frac{N ^ 3}{27}\)
不然, 若N为4的倍数, 则答案即为 \(\frac{N}{2} * \frac{N}{4} * \frac{N}{4} = \frac{N ^ 3}{32}\)
不然无解
T2:
不稳定作法:
直接暴力模拟:
每一次都将整个序列扫一遍, 对可以战胜的怪物干掉, 并增长属性值
当有一回合没法干掉任何怪物时, 中止循环
总复杂度O((n ^ 2) * K) 数据水因此卡了过去
线段树
使用线段树,
维护区间内怪物 各属性值的最大/最小值
维护区间内怪物 战胜后增长的各属性的和
若不知足上述2, 3条件, 继续向下递归
显然, 此作法单次查询 最多会被卡到nlogn
可是数据水因此卡了过去
正解:
创建 K 个小根堆,先把全部怪物按第一属性为关键字放入第一个堆.
每轮操做均从第一个堆开始, 检查堆顶元素对应第一属性值 是否比勇士对应属性值小.
如果, 则弹出放入第二个以第二属性值为关键字的堆.
一样的检查第二个堆的堆顶元素对应的第二属性值是否比勇士对应属性值小,
如果则弹出放入第三个以第三属性值为关键字的小根堆.....
直到第 K 个堆,若弹出第 K 个堆, 说明该怪物的 K 个属性值都小于等于勇士的属性值,
经过战胜该怪物来更新勇士的属性值.
每一个怪物最多入堆出堆 K次,因此时间复杂度为 O(KNlogN).
T3:
题目要求:
给定一结点数为N 的图, 初始图中没有边
给定M此操做, 每次操做会使图中 增长/删除 一条边
求每次修改后, 刚好匹配1, 2, ... N/2 对点的方案数
70% 数据:
题目能够转化为:
求选择k 条 没有重复端点的边的方案数 \((1 <= k <= N/2)\)
则可搜索枚举 每一条边的选择状况
每枚举一条边, 对其两端点打标记, 保证不出现 选择重复选择端点状况
当全部边枚举完后, 则找到了一个合法匹配 , 为对应答案相加便可
100% 数据:
状压 DP. 用 \(f[i][S]\) 表示前 i 个操做都考虑上之后 , 已匹配的顶点状态为S 的方案数.
因而, 加入一条新的边后, 全部方案能够分为两类, 第一类是包含新加的边, 第二类是不包含新加的边.
两类方案的方案数分别为 \(f[i-1][S-(1<<u)-(1<<v)]\) 和 \(f[i-1][S]\) ,
\(f[i][S] = f[i-1][S] + f[i-1][S-(1<<u)-(1<<v)]\)
至于删边,就是把加边逆过来,
\(f[i][S] = f[i-1][S] - f[i-1][S-(1<<u)-(1<<v)]\)
时间复杂度为 O(M*2^(N/2)).
T1:
#include <cstdio> #include <vector> #include <ctype.h> #define max(a, b) (a > b ? a : b) #define ll long long const int MARX = 1e6 + 10; //============================================================= int T; ll N, ans[MARX]; std :: vector <int> s[MARX]; //============================================================= inline int read() { int s = 1, w = 0; char ch = getchar(); for(; !isdigit(ch); ch = getchar()) if(ch == '-') s = -1; for(; isdigit(ch); ch = getchar()) w = (w << 1) + (w << 3) + (ch ^ '0'); return s * w; } //============================================================= int main() { freopen("diy.in", "r", stdin); freopen("diy.out", "w", stdout); for(int i = 1; i <= 100000; i ++) for(int j = 1; j * j <= i; j ++) if(i % j == 0) s[i].push_back(j); T = read(); while(T --) { N = (ll) read(); if(ans[N]) {printf("%lld\n", ans[N]); continue;} else ans[N] = - 1; if(N <= 10000) { for(ll i = 0, size = s[N].size(); i < size; i ++) for(ll j = i; j < size; j ++) if(s[N][i] + s[N][j] < N && N % (N - s[N][i] - s[N][j]) == 0) ans[N] = max(ans[N], s[N][i] * s[N][j] * (N - s[N][i] - s[N][j])); } else { for(ll i = 1; i <= N - 2; i ++) if(N % i == 0) for(ll j = i; j <= N - 2; j ++) if(i + j < N && N % j == 0 && N % (N - i - j) == 0) ans[N] = max(ans[N], i * j * (N - i - j)); } printf("%lld\n", ans[N]); } return 0; }
#include <bits/stdc++.h> using namespace std; int main() { freopen("diy.in", "r", stdin); freopen("diy.out", "w", stdout); ios::sync_with_stdio(false), cin.tie(0); int T; cin >> T; while(T--) { int n; cin >> n; if(n % 3 == 0) { int t = n / 3; cout << t * 1LL * t * t << '\n'; } else if(n % 4 == 0) { int t1 = n / 2; int t2 = n / 4; cout << t1 * 1LL * t2 * t2 << '\n'; } else { cout << "-1\n"; } } return 0; }
T2:
#include <cstdio> #include <ctype.h> #define ls (now << 1) #define rs (now << 1 | 1) #define max(a, b) (a > b ? a : b) #define min(a, b) (a < b ? a : b) #define ll long long const int MARXK = 10; const int MARX = 2e5 + 10; //============================================================= struct node { int L, R, use, sum; int maxa[MARXK], mina[MARXK], sumb[MARXK]; }tree[MARX << 2]; struct Monster { int a[MARXK], b[MARXK]; }mon[MARX]; int ans, T, N, K, v[MARXK]; //============================================================= inline int read() { int s = 1, w = 0; char ch = getchar(); for(; !isdigit(ch); ch = getchar()) if(ch == '-') s = -1; for(; isdigit(ch); ch = getchar()) w = (w << 1) + (w << 3) + (ch ^ '0'); return s * w; } void pushup(int now) { for(int i = 1; i <= K; i ++) tree[now].maxa[i] = max(tree[ls].maxa[i], tree[rs].maxa[i]), tree[now].mina[i] = min(tree[ls].mina[i], tree[rs].mina[i]), tree[now].sumb[i] = tree[ls].sumb[i] + tree[rs].sumb[i], tree[now].sum = tree[ls].sum + tree[rs].sum; } void Build(int now, int L, int R) { tree[now].L = L, tree[now].R = R; if(L == R) { for(int i = 1; i <= K; i ++) tree[now].maxa[i] = mon[L].a[i], tree[now].mina[i] = mon[L].a[i], tree[now].sumb[i] = mon[L].b[i]; tree[now].sum = 1; return ; } int mid = (L + R) >> 1; Build(ls, L, mid), Build(rs, mid + 1, R); pushup(now); } int search(int now) { bool flagdown = 1, flagup = 1; for(int i = 1; i <= K; i ++) { if(tree[now].maxa[i] > v[i]) flagup = 0; if(tree[now].mina[i] > v[i]) flagdown = 0; } if(flagup) { for(int i = 1; i <= K; i ++) v[i] += tree[now].sumb[i], tree[now].sumb[i] = 0, tree[now].maxa[i] = - 1, tree[now].mina[i] = MARX; int sum = tree[now].sum; tree[now].sum = 0; return sum; } if(! flagdown) return 0; int ret = 0; if(tree[ls].sum) ret += search(ls); if(tree[rs].sum) ret += search(rs); pushup(now); return ret; } //============================================================= signed main() { freopen("tower.in", "r", stdin); freopen("tower.out", "w", stdout); T = read(); while(T --) { N = read(), K = read(); ans = 0; for(int i = 1; i <= K; i ++) v[i] = read(); for(int i = 1; i <= N; i ++) { for(int j = 1; j <= K; j ++) mon[i].a[j] = read(); for(int j = 1; j <= K; j ++) mon[i].b[j] = read(); } Build(1, 1, N); while(1) { int plus = search(1); if(! plus) break; ans += plus; } printf("%d\n", ans); printf("%d", v[1]); for(int i = 2; i <= K; i ++) printf(" %d", v[i]); printf("\n"); } } //暴力: /* #include <cstdio> #include <ctype.h> #include <queue> #include <algorithm> #include <cstring> #define ll long long const int MARXK = 7; const int MARX = 1e5 + 10; //============================================================= struct Monster { int a[MARXK], b[MARXK]; }mon[MARX]; int ans, T, N, K, v[MARXK]; bool vis[MARX]; //============================================================= inline int read() { int s = 1, w = 0; char ch = getchar(); for(; !isdigit(ch); ch = getchar()) if(ch == '-') s = -1; for(; isdigit(ch); ch = getchar()) w = (w << 1) + (w << 3) + (ch ^ '0'); return s * w; } void solve1() { std :: priority_queue <std :: pair <int, int> > q; for(int i = 1; i <= K; i ++) v[i] = read(); for(int i = 1; i <= N; i ++) { int fir = read(), sec = read(); q.push(std :: make_pair(- fir, sec)); } for(; - 1 * q.top().first <= v[1]; ) { ans ++, v[1] += q.top().second; q.pop(); if(q.empty()) break; } printf("%d\n%d\n", ans, v[1]); } int search() { for(int i = 1; i <= N; i ++) if(! vis[i]) { bool flag = 1; for(int j = 1; j <= K; j ++) if(mon[i].a[j] > v[j]) {flag = 0; break;} if(flag) {vis[i] = 1; return i;} } return - 1; } //============================================================= int main() { T = read(); while(T --) { memset(vis, 0, sizeof(vis)); ans = 0; N = read(), K = read(); if(K == 1) {solve1(); continue;} for(int i = 1; i <= K; i ++) v[i] = read(); for(int i = 1; i <= N; i ++) { for(int j = 1; j <= K; j ++) mon[i].a[j] = read(); for(int j = 1; j <= K; j ++) mon[i].b[j] = read(); } for(int i = 1; i <= N; i ++) { int pos = search(); if(pos == -1) break; ans ++; for(int j = 1; j <= K; j ++) v[j] += mon[pos].b[j]; } printf("%d\n", ans); for(int i = 1; i <= K; i ++) printf("%d ", v[i]); printf("\n"); } return 0; } /* 1 4 1 1 1 1 4 2 2 3 10 1 */
#include<bits/stdc++.h> #define N 100010 #define INF 0x3f3f3f3f #define LL long long #define pb push_back #define cl clear #define si size #define lb lowwer_bound #define eps 1e-8 const LL mod=1e9+7; using namespace std; typedef pair<int,int> P; priority_queue<P,vector<P>,greater<P> >q[5]; int a[N][5],b[N][5],v[5]; namespace IO{ #define BUF_SIZE 100000 #define OUT_SIZE 100000 #define ll long long //fread->read bool IOerror=0; inline char nc(){ static char buf[BUF_SIZE],*p1=buf+BUF_SIZE,*pend=buf+BUF_SIZE; if (p1==pend){ p1=buf; pend=buf+fread(buf,1,BUF_SIZE,stdin); if (pend==p1){IOerror=1;return -1;} //{printf("IO error!\n");system("pause");for (;;);exit(0);} } return *p1++; } inline bool blank(char ch){return ch==' '||ch=='\n'||ch=='\r'||ch=='\t';} inline void read(int &x){ bool sign=0; char ch=nc(); x=0; for (;blank(ch);ch=nc()); if (IOerror)return; if (ch=='-')sign=1,ch=nc(); for (;ch>='0'&&ch<='9';ch=nc())x=x*10+ch-'0'; if (sign)x=-x; } }; int main() { freopen("tower.in", "r", stdin); freopen("tower.out", "w", stdout); int T; IO::read(T); while(T--) { int n,m; IO::read(n);IO::read(m); for(int i=0;i<m;i++) while(!q[i].empty()) q[i].pop(); for (int i=0;i<m;i++) IO::read(v[i]); for (int i=1;i<=n;i++) { for (int j=0;j<m;j++) IO::read(a[i][j]); for (int j=0;j<m;j++) IO::read(b[i][j]); q[0].push(P(a[i][0],i)); } int p=0,ans=0; while(1) { for (int i=0;i<m-1;i++) { while(!q[i].empty() && q[i].top().first<=v[i]) { int x=q[i].top().second; q[i].pop(); q[i+1].push(P(a[x][i+1],x)); } } while (!q[m-1].empty() && q[m-1].top().first<=v[m-1]) { ans++; int x=q[m-1].top().second; q[m-1].pop(); for (int i=0;i<m;i++) v[i]+=b[x][i]; } if (p==ans) break; p=ans; } cout<<ans<<endl;cout<<v[0]; for (int i=1;i<m;i++) cout<<' '<<v[i]; cout<<endl; } return 0; }
T3:
#include <cstdio> #include <ctype.h> #include <cstring> #define ll long long const ll mod = 1e9 + 7; const int MARX = 15; //============================================================= int T, N, M, cnt[MARX], color[MARX]; ll ans[MARX]; bool map[MARX][MARX], use[MARX]; //============================================================= inline int read() { int s = 1, w = 0; char ch = getchar(); for(; !isdigit(ch); ch = getchar()) if(ch == '-') s = -1; for(; isdigit(ch); ch = getchar()) w = (w << 1) + (w << 3) + (ch ^ '0'); return s * w; } void dfs(int now, int sum) { if(now > N) {ans[sum] = (ans[sum] + 1ll) % mod; return;} dfs(now + 1, sum); if(use[now]) return ; for(int i = now + 1; i <= N; i ++) if(map[now][i] && use[i] == 0) { map[now][i] = map[i][now] = 0, use[now] = use[i] = 1; dfs(now + 1, sum + 1); map[now][i] = map[i][now] = 1, use[now] = use[i] = 0; } } //============================================================= signed main() { freopen("sport.in", "r", stdin); freopen("sport.out", "w", stdout); T = read(); while(T --) { memset(map, 0, sizeof(map)); N = read(), M = read(); for(int i = 1; i <= M; i ++) { memset(ans, 0, sizeof(ans)); memset(use, 0, sizeof(use)); char opt; int u, v; scanf("%c", &opt); u = read(), v = read(); map[u][v] = map[v][u] = (opt == '+'); dfs(1, 0); printf("%lld", ans[1]); for(int i = 2; i <= N / 2; i ++) printf(" %lld", ans[i]); printf("\n"); } } }
/*dp[i][j]表示j状态点集的方案数*/ # include <bits/stdc++.h> using namespace std; typedef long long LL; const int mod = 1e9+7; int dp[2][1025], num[1025], sta[1025], ans[6]; void add(int &x, int y) { x += y; if(x >= mod) x -= mod; } void sub(int &x, int y) { x -= y; if(x < 0) x += mod; } int main() { freopen("sport.in", "r", stdin); freopen("sport.out", "w", stdout); char c; int n, q, T, u, v, cnt=0; for(int i=0; i<1024; ++i) { num[i]= num[i>>1]+(i&1);//i的二进制有几个1 if(~num[i]&1) sta[cnt++] = i;//sta保存偶数个1的二进制数 } for(scanf("%d",&T);T;--T) { memset(dp, 0, sizeof(dp)); scanf("%d%d",&n,&q); int now = 0; dp[0][0] = 1; while(q--) { getchar(); c = getchar(); scanf("%d%d",&u,&v); --u,--v; memset(ans, 0, sizeof(ans)); int tmp = (1<<u) | (1<<v); if(c == '+') { for(int i=0; i<cnt&&sta[i]<(1<<n); ++i) { int cur = sta[i]; dp[now^1][cur] = dp[now][cur]; if((cur&tmp) == tmp) add(dp[now^1][cur],dp[now][cur^tmp]); add(ans[num[cur]/2],dp[now^1][cur]); } } else { for(int i=0; i<cnt&&sta[i]<(1<<n); ++i) { int cur = sta[i]; dp[now^1][cur] = dp[now][cur]; if((cur&tmp) == tmp) sub(dp[now^1][cur],dp[now][cur^tmp]); add(ans[num[cur]/2],dp[now^1][cur]); } } now ^= 1; for(int i=1; i<=n/2; ++i) printf("%d%c",ans[i],i==n/2?'\n':' '); } } return 0; }