A :Three Integers | CF1311D 给定三个整数
a
≤
b
≤
c
a\le b\le c
a≤b≤c 每一次操作,可以让一个数字
+
1
+1
+1 或者
−
1
-1
−1 问你,最少操作多少次,能满足:
a
∣
b
且
b
∣
c
a|b\quad 且 \quad b|c
a∣b且b∣c
样例组数
T
≤
100
T\le 100
T≤100
1
≤
a
≤
b
≤
c
≤
1
0
4
1\le a\le b\le c\le 10^4
1≤a≤b≤c≤104
思路
因为最终是满足这个整除关系,我们直接枚举
a
a
a ,然后枚举
k
1
,
k
2
k_1,k_2
k1,k2,形成了形如
(
a
,
a
k
1
,
a
k
1
k
2
)
(a,ak_1,ak_1k_2)
(a,ak1,ak1k2) 三个数字 我们的目标就是找到最小的操作次数,就是三个数的差的绝对值的和最小即可 这样枚举,数量不会很大,大约是
O
(
n
log
2
n
)
O(n\log ^2 n)
O(nlog2n) 的
代码
#include<bits/stdc++.h>#defineIOSios::sync_with_stdio(false);cin.tie(NULL);cout.tie(NULL);
using namespace std;typedeflonglong ll;voidshow(){std::cerr << endl;}template<typename T,typename... Args>voidshow(T x,Args... args){std::cerr <<"[ "<< x <<" ] , ";show(args...);}constint MAX =1e5+50;constint MOD =1e9+7;constint INF =0x3f3f3f3f;const ll LINF =0x3f3f3f3f3f3f3f3f;constdouble EPS =1e-5;intmain(){int T;cin >> T;while(T--){int a,b,c;cin >> a >> b >> c;int ans = INF;int x,y,z;for(int i =1;i <=20000;++i)for(int j =1;i * j <=30000;++j)for(int k =1;i * j * k <=30000;++k){int tmp =abs(a-i)+abs(b-i*j)+abs(c-i*j*k);if(ans > tmp){
ans = tmp;
x = i;y = i * j;z = i * j * k;}}
cout << ans << endl;
cout << x <<" "<< y <<" "<< z << endl;}return0;}/**
*/
B:The Football Season | CF1244C
题意
B:The Football Season | CF1244C 给定
n
,
p
,
d
,
w
n,p,d,w
n,p,d,w,你需要构造出三个数字
x
,
y
,
z
x,y,z
x,y,z,满足:
x
w
+
y
d
=
p
x
+
y
+
z
=
n
x
,
y
,
z
≥
0
xw+yd=p\\ x+y+z=n\\ x,y,z\ge 0
xw+yd=px+y+z=nx,y,z≥0 这里,每一个数字都是整数
1
≤
n
≤
1
0
12
1\le n\le 10^{12}
1≤n≤1012
0
≤
p
≤
1
0
17
0\le p\le 10^{17}
0≤p≤1017
1
≤
d
<
w
≤
1
0
5
1\le d<w\le 10^5
1≤d<w≤105
思路
光看第一个等式,其实就是拓欧求
a
x
+
b
y
=
c
ax+by=c
ax+by=c 求解,我的博客里也有 算出通解之后,还要判断
x
≥
0
x\ge 0
x≥0,且
y
≥
0
y\ge 0
y≥0 且
x
+
y
≤
n
x+y\le n
x+y≤n ,只要通解带入不等式,即可得出此时
k
k
k (拓欧中通解的倍数
k
k
k) 的取值范围 然后所有的范围求交集,然后即可构造成功。
注意,交集可以使用
[
L
,
R
]
[L,R]
[L,R] 对记录,然后线段取交集的方法去做即可 这里,由于数字特别大,不等式带入时候,由于使用了
f
l
o
o
r
floor
floor 和
c
e
i
l
ceil
ceil 函数,可能误差较大,还需要使用
w
h
i
l
e
(
!
合
法
)
k
+
+
while(!合法)k++
while(!合法)k++ 之类的微调
k
k
k 的值 还有,我使用了
i
n
t
128
int128
int128 进行计算
代码
时间复杂度:
O
(
log
n
)
O(\log n)
O(logn)
#include<bits/stdc++.h>#defineIOSios::sync_with_stdio(false);cin.tie(NULL);cout.tie(NULL);
using namespace std;typedef __int128 ll;typedef __int128 lll;voidshow(){std::cerr << endl;}template<typename T,typename... Args>voidshow(T x,Args... args){std::cerr <<"[ "<< x <<" ] , ";show(args...);}constint MAX =1e5+50;constint MOD =1e9+7;constint INF =0x3f3f3f3f;const ll LINF =0x3f3f3f3f3f3f3f3f;constdouble EPS =1e-5;
ll ex_gcd(ll a,ll b,ll& x,ll& y){if(b==0){
x=1;y=0;return a;}
ll g=ex_gcd(b,a % b,x,y);
ll tmp = x;x = y; y = tmp - a / b * y;return g;}structnode{
ll l,r;}tmp[5];voiduni(int x,int y){
ll l =max(tmp[x].l,tmp[y].l);
ll r =min(tmp[x].r,tmp[y].r);
tmp[x].l = l;
tmp[x].r = r;}intmain(){
ll n,p,w,d;
n =read_lll();p =read_lll();w =read_lll();d =read_lll();
ll x0,y0,g;
ll x,y,z;
g =ex_gcd(w,d,x0,y0);if(p % g)puts("-1");else{
ll k;
k =ceil((1.0* p / g *-x0)/(d / g));
x = x0 * p / g + k * d / g;if(x <0)k++;
tmp[1].l = k,tmp[1].r = LINF;
k =floor((1.0* p / g * y0)/(w / g));
y = y0 * p / g - k * w / g;if(y <0)k--;
tmp[2].l =-LINF,tmp[2].r = k;
k =ceil((1.0* n - p / g * x0 - p / g * y0)/(d / g - w / g));
x = x0 * p / g + k * d / g;
y = y0 * p / g - k * w / g;
z = n - x - y;while(z <0){
k++;
x = x0 * p / g + k * d / g;
y = y0 * p / g - k * w / g;
z = n - x - y;}
tmp[3].l = k,tmp[3].r = LINF;
tmp[0].l =-LINF;
tmp[0].r = LINF;for(int i =1;i <=3;++i){uni(0,i);}if(tmp[0].l > tmp[0].r)puts("-1");else{
k = tmp[0].l;
x = x0 * p / g + k * d / g;
y = y0 * p / g - k * w / g;
z = n - x - y;Print(x,' ');Print(y,' ');Print(z);}}Write();return0;}
C:Modular Stability | CF1359E
题意
C:Modular Stability | CF1359E 给定
n
,
k
n,k
n,k,你需要构造出长度为
k
k
k 的序列
a
[
k
]
a[k]
a[k],满足:
1
≤
a
1
<
a
2
⋯
<
a
k
≤
n
1\le a_1<a_2\cdots <a_k\le n
1≤a1<a2⋯<ak≤n 对于任意的正整数
x
x
x,对于任意的
a
[
k
]
a[k]
a[k] 的全排列
b
[
k
]
b[k]
b[k],都满足:
(
x
%
a
1
%
a
2
⋯
%
a
k
)
=
(
x
%
b
1
%
b
2
⋯
%
b
k
)
(x\%a_1\%a_2\cdots\%a_k)=(x\%b_1\%b_2\cdots\%b_k)
(x%a1%a2⋯%ak)=(x%b1%b2⋯%bk)
1
≤
n
,
k
≤
5
⋅
1
0
5
1\le n,k\le 5\cdot 10^5
1≤n,k≤5⋅105
思路
不管
a
[
k
]
a[k]
a[k] 如何,等式左边的值就是
x
%
a
1
x\% a_1
x%a1 也就是说让等式右边成立,就必须满足所有的
a
[
k
]
a[k]
a[k] 都是
a
1
a_1
a1 的倍数 我们枚举
a
1
a_1
a1,然后从所有
a
1
a_1
a1 的倍数中,选择
k
−
1
k-1
k−1 个数字放进去,就是一个简单的组合数了
代码
时间复杂度:
O
(
n
+
k
)
O(n+k)
O(n+k)
#include<bits/stdc++.h>#defineIOSios::sync_with_stdio(false);cin.tie(NULL);cout.tie(NULL);
using namespace std;typedeflonglong ll;voidshow(){std::cerr << endl;}template<typename T,typename... Args>voidshow(T x,Args... args){std::cerr <<"[ "<< x <<" ] , ";show(args...);}constint MAX =5e5+50;constint MOD =998244353;constint INF =0x3f3f3f3f;const ll LINF =0x3f3f3f3f3f3f3f3f;constdouble EPS =1e-5;
ll qpow(ll a,ll n){/* */ll res =1LL;while(n){if(n&1)res=res*a%MOD;a=a*a%MOD;n>>=1;}return res;}
ll qpow(ll a,ll n,ll p){a%=p;ll res =1LL;while(n){if(n&1)res=res*a%p;a=a*a%p;n>>=1;}return res;}
ll npow(ll a,ll n){/* */ll res =1LL;while(n){if(n&1)res=res*a;a=a*a;n>>=1;if(res<0||a<0)return0;}return res;}
ll inv(ll a){/* */returnqpow(a,MOD-2);}
ll inv(ll a,ll p){returnqpow(a,p-2,p);}
ll fac[MAX],ivfac[MAX];voidinit(int n){
fac[0]=1;for(int i =1;i <= n;++i)fac[i]= fac[i-1]* i % MOD;
ivfac[n]=inv(fac[n]);for(int i = n -1;~i;--i)ivfac[i]= ivfac[i+1]*(i+1)% MOD;}
ll C(int n,int m){if(n <0|| m > n)return0;return fac[n]* ivfac[m]% MOD * ivfac[n - m]% MOD;}intmain(){init(500000);int n,k;cin >> n >> k;if(k ==1){
cout << n;return0;}
ll ans =0;for(int i =1;i <= n;++i){
ans =(ans +C(n/i-1,k-1))% MOD;}
cout << ans;return0;}
D:Minimax | CF1530E
题意
Minimax | CF1530E 给定一个字符串
s
s
s ,我们规定字符串的权值就是它所有位置的
b
o
r
d
e
r
border
border 的最大值 现在你需要把这个字符串重排列成
t
t
t ,我们需要使得它权值最小的情况下,字典序最小 求这个
t
t
t
∣
s
∣
≤
1
0
5
|s|\le 10^5
∣s∣≤105
思路
非常复杂的一道分类讨论的题目…
情况一:如果字符串中有一个字母只出现了一次,那么我们把这个字母(优先字典序最小)放在最前面,后面的按照字典序依次放,这样
b
o
r
d
e
r
border
border 最小为
0
0
0 例子:zaaabbbcccddd
情况二:如果字符串中只有一种字母,我们也没法排列,直接输出了 例子:zzzzzz
情况三:如果字符串有两种字母,令字典序最小字母为
p
1
p_1
p1 ,字典序次小字母为
p
2
p_2
p2 ,并记他们的出现次数
c
n
t
cnt
cnt 如果
c
n
t
[
p
1
]
≤
c
n
t
[
p
2
]
+
2
cnt[p1]\le cnt[p2]+2
cnt[p1]≤cnt[p2]+2,我们可以这么放:aabababab ,此时
b
o
r
d
e
r
=
1
border=1
border=1 否则,我们只能这么放:abbbbbbbaaaaaaaaa ,此时
b
o
r
d
e
r
=
1
border=1
border=1
情况四:如果字符串有多于两种字母 如果
c
n
t
[
p
1
]
≤
o
t
h
e
r
s
+
2
cnt[p1]\le others+2
cnt[p1]≤others+2,我们仍然可以这么放:aabacacadaefg ,此时
b
o
r
d
e
r
=
1
border=1
border=1 否则,我们取字典序第三小的字母为
p
3
p_3
p3 ,我们先放一个
p
1
p_1
p1,然后放一个
p
2
p_2
p2,然后把所有的
p
1
p_1
p1 放完,然后放一个
p
3
p_3
p3,然后其他字母按照字典序放,就是:abaaaaaacbbbcccdddeee ,此时
b
o
r
d
e
r
=
1
border=1
border=1
代码
时间复杂度:
O
(
∣
s
∣
)
O(|s|)
O(∣s∣)
#include<bits/stdc++.h>#defineIOSios::sync_with_stdio(false);cin.tie(NULL);cout.tie(NULL);
using namespace std;typedeflonglong ll;voidshow(){std::cerr << endl;}template<typename T,typename... Args>voidshow(T x,Args... args){std::cerr <<"[ "<< x <<" ] , ";show(args...);}constint MAX =1e5+50;constint MOD =998244353;constint INF =0x3f3f3f3f;const ll LINF =0x3f3f3f3f3f3f3f3f;constdouble EPS =1e-5;char ss[MAX];int cnt[30];intmain(){int T;scanf("%d",&T);while(T--){scanf("%s",ss);int p1,p2,p3,p4 =0;int zhonglei =0;for(int i =0;i <26;++i)cnt[i]=0;for(int i =0,ed =strlen(ss);i < ed;++i){
cnt[ss[i]-'a']++;if(cnt[ss[i]-'a']==1)zhonglei++;}for(int i =0;i <26;++i)if(cnt[i]){
p1 = i;break;}for(int i = p1+1;i <26;++i)if(cnt[i]){
p2 = i;break;}for(int i = p2+1;i <26;++i)if(cnt[i]){
p3 = i;break;}for(int i =0;i <26;++i)if(cnt[i]==1){
p4 = i;break;}if(cnt[p4]==1){putchar('a'+ p4);cnt[p4]--;for(int i =0;i <26;++i)for(int j =1;j <= cnt[i];++j)putchar('a'+ i);}elseif(zhonglei ==1){for(int i =1;i <= cnt[p1];++i)printf("%c",'a'+ p1);}elseif(zhonglei ==2){if(cnt[p1]> cnt[p2]+2){putchar('a'+ p1);cnt[p1]--;for(int i =1;i <= cnt[p2];++i)putchar('a'+ p2);for(int i =1;i <= cnt[p1];++i)putchar('a'+ p1);}else{putchar('a'+ p1);cnt[p1]--;while(1){if(!cnt[p1]&&!cnt[p2])break;if(cnt[p1])putchar('a'+ p1),cnt[p1]--;if(cnt[p2])putchar('a'+ p2),cnt[p2]--;}}}else{if(cnt[p1]-2>strlen(ss)- cnt[p1]){putchar('a'+ p1);cnt[p1]--;putchar('a'+ p2);cnt[p2]--;for(int i =1;i <= cnt[p1];++i)putchar('a'+ p1);putchar('a'+ p3);cnt[p3]--;for(int i = p2;i <26;++i)for(int j =1;j <= cnt[i];++j)putchar('a'+ i);}else{putchar('a'+ p1);cnt[p1]--;for(int i =1;i <= cnt[p1];++i){putchar('a'+ p1);if(cnt[p2]){putchar('a'+ p2);
cnt[p2]--;while(p2 <26&& cnt[p2]==0)p2++;}}for(int i = p2;i <26;++i)for(int j =1;j <= cnt[i];++j)putchar('a'+ i);}}puts("");}return0;}
E:The Number of Pairs | CF1499D
题意
E:The Number of Pairs | CF1499D 给定
c
,
d
,
x
c,d,x
c,d,x,求有多少对正整数
(
a
,
b
)
(a,b)
(a,b),满足:
c
⋅
l
c
m
(
a
,
b
)
−
d
⋅
gcd
(
a
,
b
)
=
x
c\cdot lcm(a,b)-d\cdot \gcd(a,b)=x
c⋅lcm(a,b)−d⋅gcd(a,b)=x
1
≤
c
,
d
,
x
≤
1
0
7
1\le c,d,x\le 10^7
1≤c,d,x≤107
思路
我们分解
a
=
∏
p
i
s
i
a=\prod p_i^{s_i}
a=∏pisi ,
b
=
∏
p
i
t
i
b=\prod p_i^{t_i}
b=∏piti 根据定义,
l
c
m
=
∏
p
i
max
{
s
i
,
t
i
}
lcm=\prod p_i^{\max\{s_i,t_i\}}
lcm=∏pimax{si,ti} ,
gcd
=
∏
p
i
min
{
s
i
,
t
i
}
\gcd=\prod p_i^{\min\{s_i,t_i\}}
gcd=∏pimin{si,ti} 首先容易得到
gcd
∣
l
c
m
\gcd|lcm
gcd∣lcm,我们令
l
c
m
=
r
⋅
gcd
lcm=r\cdot \gcd
lcm=r⋅gcd,带入得到:
gcd
(
a
,
b
)
=
x
c
r
−
d
\gcd(a,b)=\frac{x}{cr-d}
gcd(a,b)=cr−dx 由于
gcd
(
a
,
b
)
\gcd(a,b)
gcd(a,b) 一定是一个整数,容易得到
gcd
(
a
,
b
)
\gcd(a,b)
gcd(a,b) 一定是
x
x
x 的一个因子 那我们
O
(
x
)
O(\sqrt x)
O(x) 去枚举
x
x
x 的所有因子
p
p
p,我们就相当于是枚举所有的
gcd
(
a
,
b
)
=
p
\gcd(a,b)=p
gcd(a,b)=p 我们带入式子,就可以得到
l
c
m
(
a
,
b
)
=
x
+
p
d
c
lcm(a,b)=\frac{x+pd}{c}
lcm(a,b)=cx+pd,也必须要满足
c
∣
(
x
+
p
d
)
c|(x+pd)
c∣(x+pd) 还必须要满足
gcd
∣
l
c
m
\gcd | lcm
gcd∣lcm
那么问题来了,我们得到了
gcd
(
a
,
b
)
=
G
\gcd(a,b)=G
gcd(a,b)=G,
l
c
m
(
a
,
b
)
=
L
lcm(a,b)=L
lcm(a,b)=L 此时的满足要求的
(
a
,
b
)
(a,b)
(a,b) 对有多少呢?注意到我们必须
O
(
1
)
O(1)
O(1) 去得到 反过来看定义:根据定义,
l
c
m
=
∏
p
i
max
{
s
i
,
t
i
}
lcm=\prod p_i^{\max\{s_i,t_i\}}
lcm=∏pimax{si,ti} ,
gcd
=
∏
p
i
min
{
s
i
,
t
i
}
\gcd=\prod p_i^{\min\{s_i,t_i\}}
gcd=∏pimin{si,ti} 如果
s
i
=
t
i
s_i=t_i
si=ti ,那么
p
i
p_i
pi 的次数,
a
,
b
a,b
a,b 两个数都是相同的。 但是如果
s
i
≠
t
i
s_i\ne t_i
si=ti,那么可以
s
i
>
t
i
s_i>t_i
si>ti ,也可以
s
i
<
t
i
s_i<t_i
si<ti ,也就是说对于这个
p
i
p_i
pi,我们的
(
a
,
b
)
(a,b)
(a,b) 对于这个质因数有两种选择
也就是说,我们令
l
g
=
L
/
G
lg=L/G
lg=L/G,计算出
l
g
lg
lg 有多少个不同的质因子的个数
s
h
u
shu
shu ,我们的答案就是
2
s
h
u
2^{shu}
2shu 这个可以在我们埃筛的过程中实现
代码
时间复杂度:
O
(
x
log
x
)
O(x\log x)
O(xlogx)
#include<bits/stdc++.h>#defineIOSios::sync_with_stdio(false);cin.tie(NULL);cout.tie(NULL);
using namespace std;typedeflonglong ll;voidshow(){std::cerr << endl;}template<typename T,typename... Args>voidshow(T x,Args... args){std::cerr <<"[ "<< x <<" ] , ";show(args...);}constint MAX =2e7+50;constint MOD =1e9+7;constint INF =0x3f3f3f3f;const ll LINF =0x3f3f3f3f3f3f3f3f;constdouble EPS =1e-5;int cnt[MAX];
bool vis[MAX];
ll p2[150];voidinit(int n){for(int i =2;i <= n;++i){if(vis[i])continue;for(int j =1;i * j <= n;++j){
vis[i * j]=1;
cnt[i * j]++;}}}intmain(){init(20000000);
p2[0]=1;for(int i =1;i <=100;++i){
p2[i]= p2[i-1]*2;}
IOS;int T;cin >> T;while(T--){
ll c,d,x;cin >> c >> d >> x;
ll ans =0;for(ll g =1;g * g <= x;++g){if(x % g)continue;
ll l = x + d * g;if(l % c ==0){
l = l / c;
ll lg = l / g;if(l % g ==0)ans += p2[cnt[lg]];}
l = x + d *(x / g);if(g * g != x && l % c ==0){
l = l / c;
ll lg = l /(x / g);if(l %(x / g)==0)ans += p2[cnt[lg]];}}
cout << ans << endl;}return0;}