AtCoder Beginner Contest 367题解
感觉AtCoder的题写了更有收获一点……
A
判断一天中某个时间是否被夹在两个时间内
看到jiangly用模运算,学到了一点点……
#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=(b);++i)
#define trav(a,x) for(auto&a : x)
#define all(x) x.begin(),x.end()
#define sz(x) (int) x.size()
typedef std::pair<int,int> pii;
typedef std::vector<int> vi;
typedef long long ll;
void work()
{
int A,B,C;
std::cin>>A>>B>>C;
if(B<C)
{
std::cout<<((B<=A&&A<C)?"No\n":"Yes\n");
}
else
{
std::cout<<((B<=A&&A<23||0<=A&&A<C)?"No\n":"Yes\n");
}
}
int main()
{
std::cin.tie(0);
std::ios::sync_with_stdio(0);
int t=1;
//std::cin>>t;
while(t--)
work();
return 0;
}
B
#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=(b);++i)
#define trav(a,x) for(auto&a : x)
#define all(x) x.begin(),x.end()
#define sz(x) (int) x.size()
typedef std::pair<int,int> pii;
typedef std::vector<int> vi;
typedef long long ll;
void work()
{
double x;
std::cin>>x;
std::cout<<x<<'\n';
}
int main()
{
std::cin.tie(0);
std::cin.sync_with_stdio(0);
int t=1;
//std::cin>>t;
while(t--)
work();
return 0;
}
C
#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=(b);++i)
#define trav(a,x) for(auto&a : x)
#define all(x) x.begin(),x.end()
#define sz(x) (int) x.size()
typedef std::pair<int,int> pii;
typedef std::vector<int> vi;
typedef long long ll;
void work()
{
int n,k;
std::cin>>n>>k;
std::vector<int> R(n),a;
rep(i,0,n-1) std::cin>>R[i];
std::vector<std::vector<int> > ans;
auto dfs=[&](auto self,int now,int sum) -> void
{
if(now==n)
{
if(sum%k==0) ans.push_back(a);
return;
}
rep(i,1,R[now])
{
a.push_back(i);
self(self,now+1,sum+i);
a.pop_back();
}
};
dfs(dfs,0,0);
rep(i,0,sz(ans)-1)
{
trav(j,ans[i])
std::cout<<j<<' ';
std::cout<<'\n';
}
}
int main()
{
std::cin.tie(0);
std::cin.sync_with_stdio(0);
int t=1;
//std::cin>>t;
while(t--)
work();
return 0;
}
D
有 n n n个点围成一圈,其中从第 i i i个点到第 i + 1 i+1 i+1个点需要走 A i A_i Ai的距离
求有序数对 ( s , t ) (s,t) (s,t)的个数,使得 s s s走到 t t t的距离是 M M M的倍数
2 ≤ n ≤ 2 e 5 2 \le n \le 2e5 2≤n≤2e5
思路: M M M的倍数,如果想到取模这题迎刃而解
直接做一个前缀和s[t]和s[s]在模 M M M域下相等即可
#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=(b);++i)
#define trav(a,x) for(auto&a : x)
#define all(x) x.begin(),x.end()
#define sz(x) (int) x.size()
typedef std::pair<int,int> pii;
typedef std::vector<int> vi;
typedef long long ll;
void work()
{
int n,m;
std::cin>>n>>m;
std::vector<int> a(2*n);
std::vector<ll> s(2*n+1);
ll ans=0;
rep(i,0,n-1)
{
std::cin>>a[i];
rep(i,0,n-1) a[i+n]=a[i];
rep(i,0,2*n-1) s[i+1]=(s[i]+a[i])%m;
std::map<int,int> mp;
rep(i,1,n-1) mp[s[i]]++;
rep(i,0,n-1)
{
ans+=mp[s[i+n]];
mp[s[i+n]]++;
mp[s[i+1]]--;
}
std::cout<<ans<<'\n';
}
int main()
{
std::cin.tie(0);
std::cin.sync_with_stdio(0);
int t=1;
//std::cin>>t;
while(t--)
work();
return 0;
}
E
给定一个大小为 n n n的排列 X X X,给定一个数组 A A A
每次进行如下操作,对于所有的 i i i
令 B i = A X i B_i=A_{X_i} Bi=AXi
问第 k k k次操作后的 B B B序列
1 ≤ n ≤ 2 e 5 1 \le n \le 2e5 1≤n≤2e5
k ≤ 1 e 18 k \le 1e18 k≤1e18
思路:
首先由于 X X X是一个排列,所以如果我们将上一步的位置和下一步的位置连一条有向边
会得到一些环,但是即使对环的大小取模,剩下的操作步数也是 n n n级别的,我们操作一次的复杂度是 O ( n ) O(n) O(n)
考虑倍增,对于环上某个点,我们可以快速预处理出它置换 2 x 2^x 2x次后的位置,因为 X X X对自己作置换相当于是 A A A作了2倍的操作
#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=(b);++i)
#define trav(a,x) for(auto&a : x)
#define all(x) x.begin(),x.end()
#define sz(x) (int) x.size()
typedef std::pair<int,int> pii;
typedef std::vector<int> vi;
typedef long long ll;
void work()
{
int n;
ll k;
std::cin>>n>>k;
std::vector<int> X(n),Y(n);
rep(i,0,n-1)
{
std::cin>>X[i];X[i]--;
}
std::iota(Y.begin(),Y.end(),0);
while(k)
{
if(k&1)
{
rep(i,0,n-1)
Y[i]=X[Y[i]];
}
std::vector<int> tmp(n);
rep(i,0,n-1)
tmp[i]=X[X[i]];
X=std::move(tmp);k>>=1;
//std::move()这里是将tmp转移到X这个vector,不用'='是避免深拷贝
}
std::vector<int> a(n),b(n);
rep(i,0,n-1)
std::cin>>a[i];
rep(i,0,n-1)
{
b[i]=a[Y[i]];
std::cout<<b[i]<<' ';
}
std::cout<<'\n';
}
int main()
{
std::cin.tie(0);
std::cin.sync_with_stdio(0);
int t=1;
//std::cin>>t;
while(t--)
work();
return 0;
}
F
给定 A , B A,B A,B序列
Q Q Q个询问,每次询问 L , R , l , r L,R,l,r L,R,l,r,问 A L … … A R A_L……A_R AL……AR和 B l … … B r B_l……B_r Bl……Br重排后能否一致
1 ≤ n ≤ 2 e 5 1 \le n \le 2e5 1≤n≤2e5
A i , B i ≤ n A_i,B_i \le n Ai,Bi≤n
使用哈希
我们需要构建这么一种哈希映射,使得某两段区间所有的数,它们的数量都相等,哈希值才相等
因为$A[i]\le 2e5 ,所以我们取一个 ,所以我们取一个 ,所以我们取一个base=1145141 进制数,出现了一个 进制数,出现了一个 进制数,出现了一个A[i] 则加一个 则加一个 则加一个base^{A[i]}$
#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=(b);++i)
#define trav(a,x) for(auto&a : x)
#define all(x) x.begin(),x.end()
#define sz(x) (int) x.size()
typedef std::pair<int,int> pii;
typedef std::vector<int> vi;
typedef long long ll;
using u64=unsigned long long;
constexpr u64 P=u64(1e18)+9;
constexpr u64 base=1145141;
void work()
{
int n,q;
std::cin>>n>>q;
std::vector<int> a(n),b(n);
std::vector<u64> pw(n+1);
pw[0]=1;
rep(i,0,n-1)
pw[i+1]=(pw[i]*base)%P;
rep(i,0,n-1) std::cin>>a[i];
rep(i,0,n-1) std::cin>>b[i];
std::vector<u64> ha(n+1),hb(n+1);
rep(i,0,n-1)
{
ha[i+1]=(ha[i]+pw[a[i]])%P;
hb[i+1]=(hb[i]+pw[b[i]])%P;
}
while(q--)
{
int l,r,L,R;
std::cin>>l>>r>>L>>R;
l--;r--;L--;R--;
if((ha[r+1]-ha[l]+P)%P==(hb[R+1]-hb[L]+P)%P) std::cout<<"Yes\n";
else std::cout<<"No\n";
}
}
int main()
{
std::cin.tie(0);
std::cin.sync_with_stdio(0);
int t=1;
//std::cin>>t;
while(t--)
work();
return 0;
}
G(多项式)
多项式,不会,以后补