2025-10-30 ZYZOJ Star(斯达)模拟赛 hetao1733837的record
比赛背景:很抱歉打扰大家,本人于2025年10月30日查出周期性蛋白脂肪缺乏症,学名lnsanus lovis,是一种广泛存在的慢性病,易感人群多为年轻群体,目前暂无有效的治愈方法,只能使用美国公司Kentucky Fired chicken开发的制剂Firend animal protein,经由食道对胃于小肠中受体进行靶向治疗缓解症状,今天该公司降低药物售价的日子,资助50帮我治疗该慢性病。
T1.palindrome
提交链接:题目详情 - palindrome - ZYZOJ
严肃认为数据过于水了。
题面
样例
输入:
4
4
1 1 2 4
3
2 2 2
5 
1 1 1 1 1
5
1 1 2 2 3输出:
3
6
1
3分析
这不是烫题吗?我们发现,偶数是一定可行的,然而奇数必须放在中间处理。那么把偶数拆分成长度为2的pair,每个奇数均摊,就可保证最短串最长了。而对于全是偶数,自然是直接相加即可。
正解
#include <bits/stdc++.h>
using namespace std;
const int N = 50005;
int T, n, a[N];
int main(){freopen("palindrome.in", "r", stdin);freopen("palindrome.out", "w", stdout);ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);cin >> T;while (T--){cin >> n;int cnt_pair = 0;int cnt_1 = 0;long long sum = 0;for (int i = 1; i <= n; i++){cin >> a[i];cnt_pair += (a[i] / 2);if (a[i] % 2 == 1){cnt_1++;}sum += a[i];}if (cnt_1 <= 1){cout << sum << '\n';continue;}cout << 1 + cnt_pair / cnt_1 * 2 << '\n';}
}T2.expression
提交窗口:题目详情 - expression - ZYZOJ
题面
样例
输入1:
5
1 4 6 8 3
+*-*输出1:
999999689输入2:
10
517974382 763433648 185159600 390253537 104798220 734850655 170422025 748232829 820177910 110047331输出2:
123105432分析
显然是区间dp吧……好吧,错误原因是认为这题是神秘思维,将*和-当成分割,然后连subtask都没过/(ㄒoㄒ)/~~
那么,我们好好想一下为啥是区间dp。主要还是因为这题按刚才思路,具备了完整的分段性质(运算符好像本来就是),同时,答案也是左右两端合并而来的。并且,神秘的数据范围给出了,机房大佬击球手说这就是区间dp的上线。好,考虑状态即转移。
设表示
一段计算的期望结果
转移即为
最后还需乘上
时间复杂度
正解
#include <bits/stdc++.h>
#define int long long
#define mod 1000000007
using namespace std;
const int N = 1005;
int n, dp[N][N];
int f[N]; //阶乘
int c[N][N]; //组合数
char op[N];
signed main(){freopen("expression.in","r",stdin);freopen("expression.out","w",stdout); ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);cin >> n;f[0] = 1;for (int i = 1; i <= n; i++){cin >> dp[i][i];f[i] = f[i - 1] * i % mod;c[i][0] = 1;} for (int i = 1; i < n; i++) cin >> op[i];c[0][0] = 1;for (int i = 1; i <= n; i++){for (int j = 1; j <= n; j++){c[i][j] = (c[i - 1][j] + c[i - 1][j - 1]) % mod;}}for (int l = 2; l <= n; l++){ //lenfor (int i = 1; i + l - 1 <= n; i++){int j = i + l - 1;for (int k = i; k < j; k++){int x = c[j - 1 - i][k - i];if (op[k] == '+') dp[i][j] = (dp[i][j] + (f[k - i] * dp[k + 1][j] % mod + f[j - k - 1] * dp[i][k] % mod) * x % mod) % mod;if (op[k] == '-') dp[i][j] = (dp[i][j] + (f[j - k - 1] * dp[i][k] % mod - f[k - i] * dp[k + 1][j] % mod) * x % mod + mod) % mod;if (op[k] == '*') dp[i][j] = (dp[i][j] + dp[i][k] * dp[k + 1][j] % mod * x % mod) % mod;}}}cout << dp[1][n];return 0;
}T3.square
提交链接:题目详情 - square - ZYZOJ
题面
样例:
输入1:
6 4输出1:
19输入2:
100 20输出2:
368723819分析
传言是神秘的状压dp,然而作为蒟蒻的我并非会……
浅写一下吧……
然后我们发现当时,质数少得可怜,直接暴力。
但题目数据居然是,那么我们引入根号分治的思想,对于
的暴力枚举,剩余的进行状压(即选或不选)。
状压dp记录2~19质因子使用情况,剩下每个分为一组。
用dp[i][j][S]表示前i组数字,选了j个,前面8个质因子使用情况为S的方案数,然后要求每个组只能选一个,这样的方案数,直接计算即可。
然后就没了!?
正解
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 610, mod = 1e9 + 7;
int n, lim, isp[N], p[N], idx, a[N], m, cnt[N], mk[N], ans, dp[10][10][N], up, f[N], lst[10][10][N];
int c[N][N];
vector<int> v[N];
signed main(){freopen("square.in", "r", stdin);freopen("square.out", "w", stdout);ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);cin >> n >> lim;f[0] = 1;for (int i = 1; i <= n; i++) c[i][0] = 1;for (int i = 2; i <= n; i++){if (isp[i]) continue;p[++idx] = i;for (int j = 2 * i; j <= n; j+=i) isp[j] = 1;}c[0][0] = 1;for (int i = 1; i <= n; i++){for (int j = 1; j <= n; j++){c[i][j] = (c[i - 1][j] + c[i - 1][j - 1]) % mod;}}for (int i = 1; i <= idx; i++) if (p[i] * p[i] <= n) up++;for (int i = 2; i <= n; i++){int x = i, f = 0, ff = 0;for (int j = 1; j <= up; j++){if (x % p[j]) continue;f |= (1 << j - 1);x /= p[j];if (x % p[j]) continue;ff = 1;break;}if (ff) continue;a[++m] = i;cnt[m] = f;mk[m] = (x != 1);if (mk[m]) v[x].push_back(m);} dp[0][0][0] = 1;for (int i = 1; i <= m; i++){if ((!cnt[i]) || mk[i]) continue;for (int j = 0; j <= up; j++){for (int k = up; k >= 1; k--){for (int l = 0; l < (1 << up); l++){if ((l | cnt[i]) != l) continue;if (j >= mk[i] && k >= 1) dp[j][k][l] = (dp[j][k][l] + dp[j - mk[i]][k - 1][l ^ cnt[i]]) % mod;}}}}for (int r = p[up] + 1; r <= n; r++){for (int j = 0; j <= up; j++) for (int k = 0; k <= up; k++) for (int l = 0; l < (1 << up); l++) lst[j][k][l] = dp[j][k][l];for (int i : v[r]){if (!cnt[i]) continue;;for (int j = 0; j <= up; j++){for (int k = up; k >= 1; k--){for (int l = 0; l < (1 << up); l++){if ((l | cnt[i]) != l) continue;if (j >= mk[i] && k >= 1) dp[j][k][l] = (dp[j][k][l] + lst[j - mk[i]][k - 1][l ^ cnt[i]]) % mod;}}}}}for (int i = 1; i <= lim; i++){for (int j = 0; j <= up; j++){for (int k = 0; k <= min(lim, up); k++){for (int l = 0; l < (1 << up); l++){ans = (ans + dp[j][k][l] * c[idx - up - j + 1][i - k] % mod) % mod;}}}}cout << ans;return 0;
}T4.color
提交链接:题目详情 - color - ZYZOJ
题面
样例
输入
3 3
???
?R?
???输出
7大家猜我会吗?
直接上代码!
分析
首先一个条件是每个2×2的子矩形,里面的红色和蓝色个数是一样多的。如果棋盘中有两个相邻的元素同色,那么有如下
????BB????
????RR????
????BB????
????RR????
...
同时,对于每一列也一定是RB交替的,这样也一定满足条件。如果没有相邻的同色,那么整个矩形是红蓝相间的,也满足条件。换句话来说,把所有(i,j)满足i+j是偶数的位置,颜色红蓝反转,那么一定是所有行都同色或者所有列都同色。于是可以计算所有行同色所有列同色方案,减去两个都同色的情况即可.
正解
#include<bits/stdc++.h>
#define int long long
#define N 1005
#define mod 1000000007
using namespace std;
int T=1,n,m,res;
char a[N][N],b[N][N];
int check(){int sum=1;for(int i=1;i<=n;i++){bool f1=1,f2=1;for(int j=1;j<=m;j++){if(j&1)b[i][j]='R';else b[i][j]='B';if(a[i][j]!='?'&&a[i][j]!=b[i][j]){f1=0;break;}}for(int j=1;j<=m;j++){if(j&1)b[i][j]='B';else b[i][j]='R';if(a[i][j]!='?'&&a[i][j]!=b[i][j]){f2=0;break;}}if(!f1&&!f2)return 0;if(f1&&f2)(sum*=2)%=mod;}return sum;
}
void solve(int cs){cin>>n>>m;for(int i=1;i<=n;i++){for(int j=1;j<=m;j++){cin>>a[i][j];}}res=check();bool flag=1;for(int i=1;i<=n;i++){for(int j=1;j<=m;j++){if(a[i][j]=='?')continue;char c;if(a[i][j]=='R'){if(i&1)c='R';else c='B';}else{if(i&1)c='B';else c='R';}if(a[1][j]!='?'&&c!=a[1][j]){flag=0;break;}a[1][j]=c;}}if(flag){int tot=1;for(int j=1;j<=m;j++){if(a[1][j]=='?')(tot*=2)%=mod;}bool f1=1,f2=1;for(int j=1;j<=m;j++){if(a[1][j]=='?')continue;if(j&1){if(a[1][j]!='R'){f1=0;break;}}else{if(a[1][j]!='B'){f1=0;break;}}}for(int j=1;j<=m;j++){if(a[1][j]=='?')continue;if(j&1){if(a[1][j]!='B'){f2=0;break;}}else{if(a[1][j]!='R'){f2=0;break;}}}if(f1)(tot+=mod-1)%=mod;if(f2)(tot+=mod-1)%=mod;(res+=tot)%=mod;}cout<<res<<'\n';
}
signed main(){freopen("color.in","r",stdin);freopen("color.out","w",stdout);ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
//	cin>>T;for(int cs=1;cs<=T;cs++){solve(cs);}return 0;
}he的机房巨佬aoao的!
