JZOJ 1121. Fix
Posted leiyuanze
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JZOJ 1121. Fix相关的知识,希望对你有一定的参考价值。
1001 Road To The 3rd Building
题意
? 一串序列,求所有连续区间数字和的期望。
思路
? 先求出前缀和(s[i] (sum_{k=1}^{i} a[k])),做如下操作
-
长度为1的区间的和加起来得到 (s[n])
-
长度为2的区间的和加起来得到 (s[n]+s[n-1]-s[1])
-
长度为3的区间的和加起来得到 (s[n]+s[n-1]+s[n-2]-s[1]-s[2])
? 规律就很明显了,再做一次前缀和的前缀和。
代码
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn = 2e5 + 7;
const int mod = 1e9 + 7;
ll T, n;
ll s[maxn];
ll qpow(ll a, ll b) {
ll ans = 1;
while(b) {
if(b & 1) ans = ans * a % mod;
a = a * a % mod;
b >>= 1;
}
return ans;
}
ll m(ll a) {
return (a % mod + mod ) % mod;
}
int main() {
ios::sync_with_stdio(false); cin.tie(0);
freopen("data.in", "r", stdin);
//freopen("data.out", "w", stdout);
cin >> T;
while(T--) {
cin >> n;
for(int i = 1; i <= n; i++) cin >> s[i];
for(int i = 1; i <= n; i++) s[i] = (s[i] + s[i-1])%mod;
for(int i = 1; i <= n; i++) s[i] = (s[i] + s[i-1])%mod;
ll ans = 0, temp = 0;
for(int i = 1; i <= n; i++) {
ans += m(m(s[n]-s[n-i]-s[i-1]) * qpow(i, mod - 2) % mod);
ans %= mod;
}
ans = ans * qpow(n*(n+1)/2%mod, mod -2) % mod;
cout << m(ans) << endl;
}
return 0;
}
1002 Little Rabbit‘s Equation
题意
? 给一个四则运算公式,判断能满足这个公式的最小进制。
思路
? 直接模拟,需要注意除法不是整数除法,所以判断的时候使用(b*c==a)。
代码
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn = 1e5 + 7;
const int mod = 1e9 + 7;
string s;
map<char, int> mp;
void init() {
mp[‘0‘] = 0; mp[‘1‘] = 1; mp[‘2‘] = 2; mp[‘3‘] = 3;
mp[‘4‘] = 4; mp[‘5‘] = 5; mp[‘6‘] = 6; mp[‘7‘] = 7;
mp[‘8‘] = 8; mp[‘9‘] = 9; mp[‘A‘] = 10; mp[‘B‘] = 11;
mp[‘C‘] = 12; mp[‘D‘] = 13; mp[‘E‘] = 14; mp[‘F‘] = 15;
}
ll convert(int base, string num) {
ll ans = 0, p = 1;
for(int i = num.size() - 1; i >= 0; i--) {
ans += mp[num[i]] * p;
p = p * base;
}
return ans;
}
bool judge(int base, string a, char opt, string b, string c) {
ll na = convert(base, a);
ll nb = convert(base, b);
ll nc = convert(base, c);
if(opt == ‘+‘) return na + nb == nc;
if(opt == ‘-‘) return na - nb == nc;
if(opt == ‘*‘) return na * nb == nc;
return nc * nb == na;
}
int main() {
ios::sync_with_stdio(false); cin.tie(0);
freopen("data.in", "r", stdin);
//freopen("data.out", "w", stdout);
init();
while(cin >> s) {
string num[3];
num[0] = num[1] = num[2] = "";
int now = 0, ans = -1; char opt;
for(int i = 0; i < s.size(); i++) {
if(mp.count(s[i])) num[now] += s[i];
else if(s[i] != ‘=‘) {
opt = s[i];
now++;
}
else now++;
}
int base = 2;
for(int _ = 0; _ < 3; _++) {
for(char ch: num[_]) {
if(ch <= ‘9‘) base = max(base, ch - ‘0‘ + 1);
else base = max(base, ch - ‘A‘ + 11);
}
}
for(int i = base; i <= 16; i++) {
if(judge(i, num[0], opt, num[1], num[2])) {
ans = i;
break;
}
}
cout << ans << endl;
}
return 0;
}
1006 A Very Easy Graph Problem
题意
? 一个无向连通图,求所有的1点到0点的最短距离的路径和。
思路
? 考虑到第(i)条边的长度为(2^i),而(sum_{i=0}^{n-1}2^i = 2^n-1)。所以需要尽量使用前面的边,按输入顺序求最小生成树即可。然后按照一个方向遍历最小生成树,记录每一个点顺着这个方向能到达的1类点和0类点。
? 最终答案就是按照遍历顺序求每条边的贡献
代码
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn = 1e5 + 7;
const int mod = 1e9 + 7;
int T, n, m, cnt[2], ans = 0;
int a[maxn], fa[maxn], nxt[maxn][2];
vector<pair<int, int>> G[maxn];
int find(int x) {
return x == fa[x]?fa[x]:(fa[x] = find(fa[x]));
}
int qpow(int a, int b) {
int ans = 1;
while(b) {
if(b & 1) ans = (ll)ans * a % mod;
a = (ll)a * a % mod;
b >>= 1;
}
return ans;
}
void dfs(int u, int from) {
nxt[u][a[u]]++;
for(auto p: G[u]) {
if(p.first==from) continue;
dfs(p.first, u);
nxt[u][0] += nxt[p.first][0];
nxt[u][1] += nxt[p.first][1];
}
// 遍历每一个点,与点直接相连的边的贡献为nxt[u][0]*(cnt1-nxt[u][1])*w + nxt[u][1]*(cnt0-nxt[u][0])*w;
for(auto p: G[u]) {
if(p.first == from) continue;
ans = ((ll)ans + (ll)nxt[p.first][0] * (cnt[1] - nxt[p.first][1]) % mod * p.second) % mod;
ans = ((ll)ans + (ll)nxt[p.first][1] * (cnt[0] - nxt[p.first][0]) % mod * p.second) % mod;
}
}
int main() {
ios::sync_with_stdio(false); cin.tie(0);
freopen("data.in", "r", stdin);
//freopen("data.out", "w", stdout);
cin >> T;
while(T--) {
cin >> n >> m;
cnt[0] = cnt[1] = ans = 0;
for(int i = 1; i <= n; i++) {
cin >> a[i];
cnt[a[i]]++;
nxt[i][0] = nxt[i][1] = 0;
fa[i] = i;
G[i].clear();
}
// 最小生成树
for(int i = 1; i <= m; i++) {
int u, v, w;
cin >> u >> v;
w = qpow(2, i);
int x = find(u), y = find(v);
if(x == y) continue;
fa[x] = y;
G[u].push_back({v, w});
G[v].push_back({u, w});
}
dfs(1, -1);
cout << ans << endl;
}
return 0;
}
1009 Divisibility
题意
? 如下定义(y=overline{c_{1} c_{2} cdots c_{n}}),(f(y)=sum_{i=1}^{n} c_{i}, ext { if } underbrace{f(f(cdots f(y) cdots))}_{infty}) 。
? 命题:对于b进制下任意一个数字是否都有 (f(y))能被(x)整除,则(y)能被(x)整除,否者不能被(x)整除。
? 问命题是否成立
思路
? 考虑将一个数分解为(num=a_nb^n+a_{n-1}b^{n-1}+...+a_2b^2+a_1b^1+a_0)。
? 要使各位数之和(sum\%x == num\%x),也就是(b^n\%x=1,quad b^{n-1}\%x=1, quad..., quad b^1\%x=1),即(b\%x=1)。
? 因此对于(b)进制下,当(x=b-1)时命题成立。
代码
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn = 1e5 + 7;
const int mod = 1e9 + 7;
int T;
ll n, x;
int a[maxn];
int main() {
ios::sync_with_stdio(false); cin.tie(0);
freopen("data.in", "r", stdin);
//freopen("data.out", "w", stdout);
cin >> T;
while(T--) {
cin >> n >> x;
n--;
if(n % x == 0) cout << "T
";
else cout << "F
";
}
return 0;
}
以上是关于JZOJ 1121. Fix的主要内容,如果未能解决你的问题,请参考以下文章