2021杭电多校赛2021“MINIEYE杯”中国大学生算法设计超级联赛签到题5题
Posted 小哈里
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2021杭电多校赛2021“MINIEYE杯”中国大学生算法设计超级联赛签到题5题相关的知识,希望对你有一定的参考价值。
Solved Pro.ID Title Ratio(Accepted / Submitted)
1001 I love cube 26.49%(880/3322)(递推)
1002 I love tree 22.47%(60/267)(树链剖分)<n条链每次加x^2>
1003 I love playing games 7.96%(9/113)
*1004 I love counting 22.74%(78/343)(01字典树)<(区间l,r内xor a)<=b的数个数>
1005 I love string 47.41%(952/2008)(找规律,快速幂)
1006 I love sequences 57.89%(11/19)
1007 I love data structure 19.81%(21/106)(线段树超时)
1008 I love exam 24.35%(198/813)(背包)
1009 I love triples 26.79%(15/56)(逆序对0101找规律)
1010 I love permutation 20.82%(61/293)
*1011 I love max and multiply 10.52%(215/2044) (贪心,位运算)
1012 I love 114514 77.98%(1091/1399)(签到,STL)
1001 I love cube
题意:
- 给出一个边长为n-1的立方体,找出在立方体点上有三个点的等边三角形的数量,点必须是整数。
思路:
- 考虑大小为1的立方体的时候有8个,然后递推
- 可以发现规律,对于边长为i的正方形,答案为
8*(n-i)^3
,取sum[1~n-1]
后答案为2[n(n-1)]^2
(或者k = 8[n(n-1)/2]^2
)
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int maxn = 1e7+10;
const int mod = 1e9+7;
LL mpow(LL a, LL x) {
if(x==0)return 1;
LL t = mpow(a, x>>1);
if(x%2==0)return t*t%mod;
return t*t%mod*a%mod;
}
int main(){
int T; cin>>T;
while(T--){
LL n; cin>>n; n%=mod;
// k = 8[n(n-1)/2]^2 = 2[n(n-1)]^2
LL k = n*(n-1)%mod*mpow(2,mod-2)%mod;//费马小定理求逆元
k = (k+mod)%mod;
k = k*k%mod;
k = 8*k%mod;
cout<<k<<"\\n";
}
return 0;
}
1005 I love string
题意:
- 给出一个操作字符串,每次按顺序取出字符放入新串的前面或后面,求新串字典序最小时有多少种构造方案。
思路:
- 因为后面只能放前面和后面,所以是固定的,所以可以发现,答案为2^(k-1),k为操作字符串第一个字母连续重复的个数。需要用到快速幂。
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int maxn = 3e6+10;
const LL mod = 1000000007;
LL mul(LL a, LL b, LL p){
LL x = 0;
while(b){
if(b&1)x=(x+a)%p;
a = (a<<1)%p;
b >>= 1;
}
return x;
}
LL pow(LL a, LL b, LL p){
LL x = 1;
while(b){
if(b&1)x = mul(x,a,p)%p;
a = mul(a,a,p)%p;
b >>= 1;
}
return x%p;
}
int main(){
ios::sync_with_stdio(false);
int T; cin>>T;
while(T--){
int n; cin>>n;
string s; cin>>s;
LL cc = 0;
for(int i = 0; i < n; i++){
if(s[i]==s[0])cc++;
else break;
}
cout<<pow(2,cc-1, mod)<<"\\n";
}
return 0;
}
1012 I love 114514
题意:
- 给出一个字符串,判断是否包含114514
思路:
- 直接string find一下
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int maxn = 3e6+10;
int main(){
ios::sync_with_stdio(false);
int T; cin>>T;
while(T--){
string s; cin>>s;
if(s.find("114514")!=string::npos){
cout<<"AAAAAA\\n";
}else{
cout<<"Abuchulaile\\n";
}
}
return 0;
}
1011 I love max and multiply
题意:
- 给出两个长为n的数组A, B,求Ck=max(Ai*Bj)并满足i&j>=k的C数组,输出C数组的和。
思路:
- 考虑求出所有的Dk=max{AiBj}并满足i&j=k,然后再从后往前取max。
- 对于i&j==k,改原式为求Dk=max{AiBj}并满足k属于i&j的,即对于A,B分别求满足k属于i,j时max(ai), min(ai), max(bi), min(bi), 然后分别相乘取最大
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int maxn = 1e6+10;
const int inf=1e9+10;
const int mod=998244353;
int a[maxn],b[maxn], A[maxn],B[maxn];
int main(){
ios::sync_with_stdio(false);
int T; cin>>T;
while(T--){
LL n; cin>>n;
for(int i = 0; i < n; i++){
cin>>a[i]; A[i]=a[i];
}
for(int i = 0; i < n; i++){
cin>>b[i]; B[i]=b[i];
}
int m=1;
while(m<n)m<<=1;
for(int i = n; i < m; i++){
A[i]=B[i]=-inf;
a[i]=b[i]=inf;
}
for(int i = 1; i < m; i<<=1){
for(int k = 0; k < n; k++){
if(!(i&k)){
A[k]=max(A[k], A[i^k]);
a[k]=min(a[k], a[i^k]);
B[k]=max(B[k], B[i^k]);
b[k]=min(b[k], b[i^k]);
}
}
}
LL t = -(LL)inf*inf, ans = 0;
for(int i = n-1; i >= 0; i--){
t = max(t, 1ll*A[i]*B[i]);
t = max(t, 1ll*A[i]*b[i]);
t = max(t, 1ll*a[i]*B[i]);
t = max(t, 1ll*a[i]*b[i]);
ans = (ans+t%mod)%mod;
}
ans = (ans+mod)%mod;
cout<<ans<<"\\n";
}
return 0;
}
1004 I love counting
题意:
- 给出一个长为n的序列,每次询问区间[l, r]内有多少数满足
xi xor a <= b
。
思路:
- 维护01字典树,每个节点记录一下子树内的所有点。
- 对于一个询问,它所包含的是树上的最多logn个子树,对每颗子树做一遍二维数点即可
//暂时不太懂 list, BIT, 01Tire, vector, struct
#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e5+10;
int head[maxn], nxt[maxn], c[maxn], ans[maxn];
struct qq{int l, r, a, b; }q[maxn];
struct node{int l, r, x,id;};
bool operator < (const node &a, const node &b){
if(a.x!=b.x)return a.x<b.x;
if(a.id!=b.id)return a.id<b.id;
return a.l<b.l;
}
vector<node>vec[maxn*20];
int n, tot, tr[maxn], ch[maxn*20][2], sum[maxn*20];
void add(int x, int y){while(x<=n)tr[x]+=y, x+=x&-x;}
int query(int x){int ans=0; while(x)ans+=tr[x],x-=x&-x;return ans;}
void query(int rt, int now, int a, int b, int id){
if(!rt && now!=16)return ;
if(now < 0){
vec[rt].push_back(node{q[id].l,q[id].r,n-q[id].r+1, id});
return ;
}
int xx=(a&(1<<now))!=0, yy = (b&(1<<now))!=0;
if(yy)vec[ch[rt][xx]].push_back(node{q[id].l, q[id].r, n-q[id].r+1, id});
xx ^= yy;
query(ch[rt][xx],now-1, a, b, id);
}
void insert(int x, int id){
int now = 0;
for(int i=16; i>=0; i--){
int xx = (x&(1<<i))!=0;
if(!ch[now][xx])ch[now][xx] = ++tot;
now = ch[now][xx];
sum[now]++;
vec[now].push_back(node{id,0,n-nxt[id]+2,0});
}
}
int main(){
ios::sync_with_stdio(false);
cin>>n;
for(int i = 1; i <= n; i++)cin>>c[i];
for(int i = n; i >= 1; i--){
if(!head[c[i]])nxt[i]=n+1;
else nxt[i]=head[c[i]];
head[c[i]]=i;
}
for(int i = 1; i <= n; i++)insert(c[i],i);
int Q; cin>>Q;
for(int i = 1; i <= Q; i++){
cin>>q[i].l>>q[i].r>>q[i].a>>q[i].b;
query(0,16,q[i].a, q[i].b, i);
}
for(int i = 1; i <= tot; i++){
sort(vec[i].begin(), vec[i].end());
for(auto it : vec[i]){
if(it.id == 0){
add(it.l, 1);
}else{
ans[it.id] += query(it.r)-query(it.l-1);
}
}
for(auto it : vec[i]){
if(it.id == 0){
add(it.l, -1);
}
}
}
for(int i = 1; i <= Q; i++)
cout<<ans[i]<<"\\n";
return 0;
}
以上是关于2021杭电多校赛2021“MINIEYE杯”中国大学生算法设计超级联赛签到题5题的主要内容,如果未能解决你的问题,请参考以下文章
2021杭电多校赛2021“MINIEYE杯”中国大学生算法设计超级联赛签到题4题
2021杭电多校赛2021“MINIEYE杯”中国大学生算法设计超级联赛签到题5题
2021杭电多校赛2021“MINIEYE杯”中国大学生算法设计超级联赛签到题5题
2021杭电多校赛2021“MINIEYE杯”中国大学生算法设计超级联赛签到题2题