昨天的 ABC 直接吧我打懵了,数学题多。
后面的两题到现在还是不会。
https://atcoder.jp/contests/abc238/tasks。
https://atcoder.jp/contests/abc238/tasks/abc238_a。
给一个 n n n,问是指数函数( 2 n 2^n 2n)和一个平方函数( n 2 n^2 n2)数据大。
如果本题 n n n 比较小,我们可以直接计算出结果然后比较。但是本题 n n n 非常大,达到 1 0 9 10^9 109,因此直接计算是不现实的。
数学上,我们知道随着 n n n 变大,指数函数结果肯定大于平方函数结果。
因此,我们只需要简单分类讨论一下就可以了。
#include
using namespace std;
typedef long long LL;
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
LL n;
cin>>n;
if (2<=n && n<=4) {
cout<<"No\n";
} else {
cout<<"Yes\n";
}
return 0;
}
https://atcoder.jp/contests/abc238/tasks/abc238_b。
简单的数学题。难度在于读题,英文比较菜,读了好久才读懂题目的意思。
给你 n n n 个切披萨的角度,问得到所有切割角度中,最大角是多少。
根据题面:rotating the pizza clockwise by D D D degrees and making another cut,就是将披萨进行循环。我们可以看成将刀进行旋转,这样我们只要将切割的角度进行累加。不要忘记披萨是一个圆,只有 360 360 360 度,我们需要对 360 360 360 取模。
假设有 N N N 个切割角度,分别为 A 1 , A 2 , … , A N A_1,A_2,\dots,A_N A1,A2,…,AN。
#include
using namespace std;
typedef long long LL;
typedef pair<LL, LL> PLL;
const int N=360;
bool d[N];//false没有切割,true切割
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
LL n;
cin>>n;
d[0]=true;//0度切割了
LL sum=0;
for (LL i=1; i<=n; i++) {
LL x;
cin>>x;
sum=(sum+x)%360;
d[sum]=true;
}
//找连续的切割的最大角度
LL res=0;
LL cur=0;
for (LL i=0; i<=360; i++) {
if (d[i%360]) {
res=max(res, cur);
cur=0;
}
cur++;
}
cout<<res<<"\n";
return 0;
}
#include
using namespace std;
typedef long long LL;
typedef pair<LL, LL> PLL;
const int N=360;
LL ans[N];
bool d[N];//false没有切割,true切割
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
LL n;
cin>>n;
LL sum=0;
LL cnt=0;
ans[++cnt]=0;
for (LL i=1; i<=n; i++) {
LL x;
cin>>x;
sum=(sum+x)%360;
ans[++cnt]=sum;//送入答案数组
}
ans[++cnt]=360;
sort(ans+1, ans+cnt+1);
//找连续的切割的最大角度
LL res=0;
for (LL i=2; i<=cnt; i++) {
res=max(res, ans[i]-ans[i-1]);
}
cout<<res<<"\n";
return 0;
}
https://atcoder.jp/contests/abc238/tasks/abc238_c。
给定一个函数 f ( x ) f(x) f(x),表示数位数量与 x x x 相同而且数据不超过 x x x 的正整数数量。给定一个 n n n,求 f ( 1 ) + f ( 2 ) + ⋯ + f ( n ) f(1)+f(2)+\dots+f(n) f(1)+f(2)+⋯+f(n) 的值,数据对 998244353 998244353 998244353 取模。
首先。我们先看 n n n 的大小。本题 n n n 为 1 0 18 10^{18} 1018,我们没有办法根据 f ( x ) f(x) f(x) 的定义直接暴力计算。但是我们要注意到 f ( x ) f(x) f(x) 的定义关键数位,也就是说 1 0 18 10^{18} 1018 的数位只有 18 18 18 位。
其次。我们来分析一下 f ( x ) f(x) f(x) 的属性。那就是找规律了。
那么 f ( 1 ) + f ( 2 ) + . . . f ( n ) f(1)+f(2)+...f(n) f(1)+f(2)+...f(n),我们可以根据位数分类讨论。
这样,本题根据 n n n 的数据范围,最多分为 18 18 18 类进行计算。
至于 f ( x ) f(x) f(x) 的累加,我们可以利用等差数列求和公式计算。
#include
using namespace std;
typedef long long LL;
typedef pair<LL, LL> PLL;
const LL MOD=998244353;
//计算1+2+...+x
LL calc(LL x) {
x%=MOD;
LL res=x;
res=(res*(res+1)/2)%MOD;
return res;
}
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
LL n;
cin>>n;
LL ans=0;
LL p10=10;
for (LL i=1; i<=18; i++) {
LL l=p10/10;//起点
LL r=min(n, p10-1);//终点
if (l<=r) {
//cout<<"calc "<
ans=(ans+calc(r-l+1))%MOD;
} else {
break;
}
p10*=10;
}
cout<<ans<<"\n";
return 0;
}
https://atcoder.jp/contests/abc238/tasks/abc238_d。
本题涉及到按位与运算。根据按位与的真值表,全 1 1 1 得 1 1 1。
根据题目可得:
x + y = s , x and y = a x+y=s, x\ \text{and}\ y=a x+y=s,x and y=a。
根据位运算特性,可以得知,当且仅当 s ≥ 2 ∗ a s \geq 2*a s≥2∗a,才有可能是 Yes。
#include
using namespace std;
using LL=long long;
using PLL=pair<LL, LL>;
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
LL T;
cin>>T;
while (T--) {
LL a,s;
cin>>a>>s;
if (2*a<=s) {
LL t=s-2*a;
if ((t&a)==0) {
cout<<"Yes\n";
continue;
}
}
cout<<"No\n";
}
return 0;
}
https://atcoder.jp/contests/abc238/tasks/abc238_e。
每次读入两个数据 l , r l,r l,r,最后问你所有数据是否包含 0 0 0 到 n n n。
本题用区间合并,DFS等方法都可以实现。
个人认为最简单的方法就是并查集。
看到包含,我们就可以使用并查集来完成。注意我们需要从 [ l − 1 , r ] [l-1, r] [l−1,r] 进行合并。合并完成后,我们查看一下 0 0 0 和 n n n 是否在同一个集合即可。
当然本题也可以区间合并来解决。
#include
using namespace std;
using LL=long long;
using PLL=pair<LL, LL>;
//DSU
const int N=2e5+10;
LL fa[N];
void init(LL n) {
for (LL i=0; i<=n; i++) {
fa[i]=i;
}
}
LL find_root(LL x) {
if (fa[x]!=x) {
fa[x]=find_root(fa[x]);
}
return fa[x];
}
bool union_set(LL x, LL y) {
x=find_root(x);
y=find_root(y);
if (x==y) {
return false;
}
fa[y]=x;
return true;
}
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
LL n,q;
cin>>n>>q;
init(n);//初始化并查集
while (q--) {
LL l,r;
cin>>l>>r;
union_set(l-1, r);
}
if (find_root(0)==find_root(n)) {
cout<<"Yes\n";
} else {
cout<<"No\n";
}
return 0;
}
暂时不会。
暂时也不会。