T1
草稿本上算一下就能得到
然后就去算,有除法的转换为乘法逆元即可
代码
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int p=998244353;
int n,m,g,ans,qwe;
struct dian
{
int x;
int y;
}q[1000010];
int gcdEx(int a,int b,int &X,int &Y)//扩展欧几里得求逆元
{
if(b==0)
{
X=1,Y=0;
return a;
}
int d=gcdEx(b,a%b,Y,X);
Y-=a/b*X;
return d;
}
int cal1(int s1,int s2)
{
s1%=p,s2%=p;
int X=0,Y=0;
gcdEx(4*s2,p,X,Y);
X=(X % p + p) % p;
return X*(s1*s1%p*m%p);
}
int cal2(int s1,int s2)
{
s1%=p,s2%=p;
int X=0,Y=0;
gcdEx(4*s2,p,X,Y);
X=(X % p + p) % p;
return (m*s2%p)+((s1*s1%p*m%p)*X)%p;
}
int cal3(int s1)
{
return (m*s1)%p*qwe;
}
signed main()
{
cin>>n>>m>>g;
int X=0,Y=0;
gcdEx(2,p,X,Y);
X=(X % p + p) % p;
qwe=X;
for(int i=1;i<=n;i++) scanf("%lld%lld",&q[i].x,&q[i].y);
for(int i=1;i<n;i++)
{
if(q[i].y==q[i+1].y) ans=(ans+cal3(q[i+1].x-q[i].x))%p;
if(q[i].y<q[i+1].y) ans=(ans+cal2(q[i+1].x-q[i].x,q[i+1].y-q[i].y))%p;
if(q[i].y>q[i+1].y) ans=(ans+cal1(q[i+1].x-q[i].x,q[i].y-q[i+1].y))%p;
}
ans=(ans*g)%p;
cout<<ans<<"J";
return 0;
}
T2
考试时只想到dp…,明明做字符串的问题要用字符串相关的算法啊,然后考虑用trie树来做,如果已知字符串长度,那就可以直接切了,可题中字符串可以无限循环,但保证每个初始字符串都不存在周期,,于是我们便考虑2个字符串相互匹配能匹配到的最长能多长,
然后题解会告诉你:
然后是一种证明
那这道题就简单了,代码
#include<bits/stdc++.h>
using namespace std;
int n,tr[20001000][2],sum,len,tot,ans;
char s[1010];
int Read()
{
int x=0,f=1;
char ch=getchar();
while(!isdigit(ch))
{
if(ch=='-')
f=-1;
ch=getchar();
}
while(isdigit(ch))
{
x=(x<<1)+(x<<3)+ch-'0';
ch=getchar();
}
return f*x;
}
void insert(char *s)
{
int u=1;
for(int i=1;i<=1000;i++)
{
int c=s[i]-'0';
if(!tr[u][c]) tr[u][c]=++tot;
else sum++;
u=tr[u][c];
}
}
int main()
{
n=Read();
tot=1;
for(int i=1;i<=n;i++)
{
scanf("%s",s+1);
len=strlen(s+1);
for(int j=len+1;j<=1000;j++)
{
if((j%len)==0)
s[j]=s[len];
else s[j]=s[j%len];
}
sum=0;
insert(s);
ans=max(ans,sum);
}
cout<<ans;
return 0;
}
T3
完全没想到能用权值线段树来做,而且要离散化一下
然后最小值位置的维护就是普通的线段树操作,问有多少人要调整就按题解说的来,没啥算法可言。
还是附个题解
代码
#include<bits/stdc++.h>
using namespace std;
const int N=4e5+10;
const int inf=0x7fffffff;
int n,m,x,b[N],a[N],pre[N],nxt[N],val[N],cnt,last,pos[N],ans;
int Read()
{
int x=0,f=1;
char ch=getchar();
while(!isdigit(ch))
{
if(ch=='-')
f=-1;
ch=getchar();
}
while(isdigit(ch))
{
x=(x<<1)+(x<<3)+ch-'0';
ch=getchar();
}
return f*x;
}
void pushup(int u)
{
val[u]=min(val[u*2],val[u*2+1]);
}
void build(int u,int l,int r)
{
if(l==r)
val[u]=pos[l];
else
{
int mid=(l+r)>>1;
build(u*2,l,mid);
build(u*2+1,mid+1,r);
pushup(u);
}
}
void modify(int u,int l,int r,int x)
{
if(l==r)
{
val[u]=++cnt;
pos[x]=cnt;
return;
}
else
{
int mid=(l+r)>>1;
if(x<=mid) modify(u*2,l,mid,x);
else modify(u*2+1,mid+1,r,x);
pushup(u);
}
}
int query(int u,int l,int r,int st)
{
if(l==r) return l;
int mid=(l+r)>>1;
if(val[u*2]<=st) return query(u*2,l,mid,st);
else return query(u*2+1,mid+1,r,st);
}
int main()
{
n=Read(),m=Read();
for(int i=1;i<=n;i++) a[i]=Read(),b[i]=a[i];
sort(b+1,b+1+n);
for(int i=1;i<=n;i++)
{
a[i]=lower_bound(b+1,b+1+n,a[i])-b;
nxt[a[i-1]]=a[i];pre[a[i]]=a[i-1];
pos[a[i]]=i;
}
build(1,1,n),cnt=n,last=a[n];
for(int i=1;i<=m;i++)
{
char s;
cin>>s;
x=Read();
int t=lower_bound(b+1,b+1+n,x)-b;
if(s=='A')
{
if(!pre[t]) cout<<-1<<endl;
else cout<<b[query(1,1,n,pos[pre[t]])]<<endl;
}
else
{
if(last==t) continue;
modify(1,1,n,t);
nxt[pre[t]]=nxt[t];
pre[nxt[t]]=pre[t];
nxt[last]=t;
pre[t]=last;
last=t;
}
}
sort(pos+1,pos+1+n);
int r=1;
ans=inf;
for(int l=1;l<=n&&r<=n;l++)
{
while(pos[r]-pos[l]+1<n&&r<=n) r++;
if(r>n||pos[r]-pos[l]+1>n) r--;
ans=min(ans,l-1+n-r);
}
cout<<ans;
return 0;
}