偶数贡献:
当
n
n
n 为奇数时,贡献为
(
n
+
1
)
/
2
(n+1)/2
(n+1)/2,
n
n
n 为偶数时,贡献为
n
/
2
n/2
n/2,显然可以合成一个式子计算
奇数贡献:
总的奇数个数
−
-
− 不满足条件的奇数个数
不满足条件的奇数 :
如果
n
%
3
=
=
0
n \% 3==0
n%3==0,最大的一个不满足条件的奇数是
<
n
/
3
−
1
< n / 3 - 1
<n/3−1 的。
否则就是
<
n
/
3
<n / 3
<n/3。
+
1
+1
+1,
/
2
/2
/2 向上取整就得到这个范围内奇数的个数
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn = 1e5 + 9;
ll n, m, k, l, r, ans;
char s[maxn];
void work()
{
scanf("%lld", &n);
ans = 0;
ans += (n + 1) / 2;
ans += (n + 1) / 2 - ((n % 3 == 0 ? n / 3 - 1 : n / 3) + 1) / 2;
printf("%lld\n", ans);
}
int main()
{
int TT;cin>>TT;while(TT--)
work();
return 0;
}
Time-division Multiplexing
题意:
n
n
n 个字符串(只包含小写字母),每个长度不超过
12
12
12,构造一个字符串
t
t
t,从
n
n
n 个字符串中第一个字符串开始,每次按顺序依次选取一个字符串的字符加入,如果一个字符串选到了最后一个,那么下次从这个字符串第一个开始选。求
t
t
t 串中最短的一个子串,满足包含
n
n
n 个字符串中所有种类的字符。
思路:所有字符串的长度的
l
c
m
lcm
lcm 的
n
n
n 倍 就是
t
t
t 的循环周期
l
c
m
lcm
lcm 最大是
5
×
7
×
8
×
9
×
11
=
27720
5 \times 7 \times 8 \times 9 \times 11 = 27720
5×7×8×9×11=27720。
问题就变成了对一个最大循环周期为
27720
n
27720n
27720n 的字符串求解。
需要注意的是,这个
t
t
t 串是无限循环串,最后的答案可能取值两个循环串之间,因此需要对两倍长度的循环节求解。
统计一下有多少中字符,模拟出
t
t
t 串的循环节并加倍,对循环节的2倍二分答案
参考题解
#include<bits/stdc++.h>
#define ll long long
#define endl '\n'
#define _ 0
using namespace std;
const int maxn = 6e6 + 9;
const ll mod = (ll)1e9 + 7;
ll n, m;
char s[109][15];
char t[maxn];// 构造的 t 串
int len[109];// 字符串长度
int pos[109];// 字符串指针
bool vis[30];
int num[30];// 统计某个字符数量,便于加减判断区间是否存在这个字符
ll kind, length;// 字符种类数 和 循环字符长度
bool check(int mid)
{
memset(num, 0, sizeof(num));
int k = 0;
for(int i = 0; i < mid; ++i)
{
if (num[t[i] - 'a'] == 0) k++;
num[t[i] - 'a']++;
}
if(kind == k) return 1;
int l = 0;
for(int r = mid; r < 2 * length; ++l, ++r)
{
if(--num[t[l] - 'a'] == 0) --k;
if(++num[t[r] - 'a'] == 1) ++k;
if(k == kind) return 1;
}
return 0;
}
void work()
{
memset(pos, 0, sizeof(pos)); memset(vis, 0, sizeof(vis));
cin >> n;
kind = 0;
for(int i = 1; i <= n; ++i)
{
cin >> s[i]; len[i] = strlen(s[i]);
for(int j = 0; j < len[i]; ++j) if(!vis[s[i][j] - 'a'])
++kind, vis[s[i][j] - 'a'] = 1;
}
bool f = 1;// 模拟出 t 串的循环节
length = 0;
while(f)
{
for(int j = 1; j <= n; ++j)
t[length++] = s[j][pos[j]], pos[j] = (pos[j] + 1) % len[j];// 0 - len[j] - 1
f = 0;
// pos[i] 全部等于0,意味着恰好一个周期,所有字符串指针指向第一个字符
for(int j = 1; j <= n; ++j) if(pos[j] != 0){
f = 1; break;
}
}
for(int j = 0; j < length; ++j)
t[length + j] = t[j];
t[length * 2] = 0;
int l = kind, r = length;// 二分答案
while(l < r)
{
int mid = (l + r) >> 1;
if(check(mid)) r = mid;
else l = mid + 1;
}
cout << l << endl;
}
int main()
{
//ios::sync_with_stdio(0);
int TT;cin>>TT;while(TT--)
work();
return ~~(0^_^0);
}
Power Sum-hdu-7105
题意:
给定一个数
n
n
n,求一个长度为
k
k
k 的数组
a
a
a ,
a
i
∈
a_i \in
ai∈ {
−
1
,
1
-1,1
−1,1},
k
∈
[
1
,
n
+
2
]
k \in [1,n+2]
k∈[1,n+2],满足下列等式
∑
i
=
1
i
=
k
a
i
×
i
2
=
n
\sum_{i=1}^{i=k}a_i \times i^2=n
i=1∑i=kai×i2=n
求一个长度为
k
k
k 的
01
01
01 串,
0
0
0 代表
a
i
=
−
1
a_i=-1
ai=−1,
1
1
1 代表
a
i
=
1
a_i=1
ai=1,满足上述等式。
思路:
这个题要发现一个性质:
(
x
+
1
)
2
(x+1)^2
(x+1)2
−
-
−
(
x
+
2
)
2
(x+2)^2
(x+2)2
−
-
−
(
x
+
3
)
2
(x+3)^2
(x+3)2
+
+
+
(
x
+
4
)
2
(x+4)^2
(x+4)2
=
=
=
4
4
4
用四个数为构造
n
n
n 贡献
4
4
4 的大小,然后
n
n
n
m
o
d
mod
mod
4
4
4
=
0
,
1
,
2
,
3
=0,1,2,3
=0,1,2,3,我们还可以发现
1
=
1
1=1
1=1,
4
−
1
=
3
4-1=3
4−1=3,
−
1
−
4
−
9
+
16
=
2
-1-4-9+16=2
−1−4−9+16=2,这样最后缺少的
1
,
2
,
3
1,2,3
1,2,3 就都构造出来了。
AC代码:
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn = 1e5 + 9;
ll n, x, k, m;
void work()
{
cin >> n;
m = n / 4;
k = n % 4;
string s = "";
for(int i = 1; i <= m; ++i)
s += "1001";
if(k == 1) s = "1" + s;
else if(k == 2) s = "0001" + s;
else if(k == 3) s = "01" + s;
cout << s.size() << endl;
cout << s << endl;
}
int main()
{
ios::sync_with_stdio(0);
int TT;cin>>TT;while(TT--)
work();
return 0;
}
Function-hdu-7106
题意:给你一个函数
g
(
x
)
=
x
g(x)=x
g(x)=x的各位和,和一个函数
f
(
x
)
f(x)
f(x),求
x
∈
[
1
,
n
]
x \in [1,n]
x∈[1,n] 时
f
(
x
)
m
i
n
f(x)_{min}
f(x)min。
思路:
∀
x
∈
[
1
,
1
0
6
]
\forall x \in [1,10^6]
∀x∈[1,106],
g
(
x
)
m
a
x
=
g
(
999999
)
=
54
g(x)_{max}=g(999999)=54
g(x)max=g(999999)=54,因此函数
g
(
x
)
∈
[
1
,
54
]
g(x) \in [1,54]
g(x)∈[1,54],我们可以预处理出来所有
g
(
x
)
g(x)
g(x) 对于取的
x
x
x 的值。枚举
g
(
x
)
g(x)
g(x) 的取值,那么
f
(
x
)
f(x)
f(x) 就是一个二次函数,三分寻找最小值即可。
f
(
x
)
=
(
A
g
(
x
)
+
B
)
x
2
+
(
C
g
2
(
x
)
+
D
g
(
x
)
)
x
f(x)=(Ag(x) + B)x^2+(Cg^2(x)+Dg(x))x
f(x)=(Ag(x)+B)x2+(Cg2(x)+Dg(x))x
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn = 1e5 + 9;
ll n, m;
ll a, b, c, d;
vector <int> v[60];
inline ll f(ll A, ll B, ll x)
{
return A * x * x + B * x;
}
void work()
{
cin >> a >> b >> c >> d >> n;
ll ans = 1e18;
for(ll i = 1; i <= 54; ++i)// 枚举 g(x)
{
if(v[i][1] > n) continue;// x可取范围不在定义域 [1,n] 内
ll l = 1, r = --upper_bound(v[i].begin(),v[i].end(), n) - v[i].begin();// r是最后一个满足小于等于n的数
ll xa = a * i + b, xb = c * i * i + d * i;
ans = min({ans, f(xa, xb, 1ll*v[i][l]), f(xa, xb, 1ll*v[i][r])});
// 如果 xa <= 0 那么取值应该为 端点最小值
// xa > 0,最小值在对称轴附近
if(xa > 0)// 三分寻找最小值
{
while(l <= r)
{
ll lmid = l + (r - l) / 3, rmid = r - (r - l) / 3;
ll fl = f(xa, xb, 1ll*v[i][lmid]), fr = f(xa, xb, 1ll*v[i][rmid]);
if(fl <= fr) r = rmid - 1;
else l = lmid + 1;
ans = min({ans, fl, fr});
}
}
}
cout << ans << endl;
}
int main()
{
ios::sync_with_stdio(0);
for(int i = 1; i <= 54; ++i) v[i].push_back(-1e9);
for(int i = 1; i <= 1e6; ++i)
{
int sum = 0, tmp = i;
while(tmp)
{
sum += tmp % 10;
tmp /= 10;
}
v[sum].push_back(i);
}
for(int i = 1; i <= 54; ++i) v[i].push_back(1e9);
int TT;cin>>TT;while(TT--)
work();
return 0;
}
Command Sequence-hdu-7108
题意:寻找子序列满足机器人在执行完这个序列之后仍在原点。
思路:计算贡献
AC代码:
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn = 1e5 + 9;
ll n, m;
ll dp[maxn][2];
char s[maxn];
void work()
{
scanf("%lld", &n);
scanf("%s",s + 1);
for(int i = 1; i <= n; ++i)
{
dp[i][0] = dp[i-1][0];
dp[i][1] = dp[i-1][1];
if(s[i] == 'U') ++dp[i][0];
else if(s[i] == 'D') -- dp[i][0];
else if(s[i] == 'L') ++dp[i][1];
else --dp[i][1];
}
ll ans = 0;
map<pair<int,int>,int> ma;
ma[{0,0}] = 1;// 注意同时为0时的贡献
for(int i = 1; i <= n; ++i)
{
pair <int,int> p = {dp[i][0], dp[i][1]};
if(!ma.count(p)) ma[p] = 1;
else ans += ma[p], ma[p]++;
}
printf("%lld\n", ans);
}
int main()
{
int TT;cin>>TT;while(TT--)
work();
return 0;
}