noip模拟72
考场
早上去上了语文课,于是回来选择只写两道题
看错了题没看见只能一个一个往里加于是主动弃掉
看起来像是一个二维树状数组就可以做的题(然而没有意识到模数不互质的严重性)
以为有单调性二分加哈希就可以了,于是先写 ,写完才发现问题所在,看起来像是后缀类的科技,直接放弃
没看
A. T1 出了个大阴间题
一看范围是状压,数是一个一个往里加的,这就提供一个很好的性质:与 产生过程无关,其贡献可以直接计算
设 表示已选集合为 ,且 的值为
显然开不下,然而发现性质只可能比集合 大 或相等,所以开两维即可
分别记录真实的 值,排列方案数,以及此时总和
点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int maxn=1e6+5;
const int mod=1e9+7;
const int maxm=40;
int n,a[maxm],all,m,val[maxm],sum[maxm],ans;
int f[maxn][maxm];//值
int g[maxn][maxm];//排列个数
int h[maxn][maxm];//和
int read(){
int x=0,f=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
while(isdigit(ch)){x=x*10+ch-48;ch=getchar();}
return x*f;
}
void modadd(int &a,int b){
a=(a+b)%mod;
}
signed main(){
freopen("repair.in","r",stdin);
freopen("repair.out","w",stdout);
n=read();m=read();
for(int i=1;i<=n;i++)a[i]=read();
for(int i=1;i<=n;i++)val[i]=val[i-1]*2+1,sum[i]=sum[i-1]+val[i];
all=(1<<n)-1;
for(int i=1;i<=n;i++)f[1<<(i-1)][0]=a[i],g[(1<<(i-1))][0]=1;
for(int i=1;i<=all;i++){
if(!f[i][0])continue;
for(int j=1;j<=n;j++){
if((1<<(j-1))&i)continue;
int S=(i|(1<<(j-1)));
for(int k=0;k<=1;k++){
if(!f[i][k])continue;
int nxt=(f[i][k]==a[j])?a[j]+1:max(f[i][k],a[j]);
// cout<<nxt<<endl;
if(nxt<f[S][0]){
if(nxt>f[S][1])f[S][1]=nxt,g[S][1]=h[S][1]=0;
if(nxt==f[S][1]){
modadd(g[S][1],g[i][k]);
modadd(h[S][1],nxt*g[i][k]%mod+h[i][k]);
}
}
else{
if(nxt>f[S][0]){
f[S][1]=f[S][0],g[S][1]=g[S][0],h[S][1]=h[S][0];
f[S][0]=nxt,g[S][0]=h[S][0]=0;
}
if(nxt==f[S][0]){
modadd(g[S][0],g[i][k]);
modadd(h[S][0],nxt*g[i][k]%mod+h[i][k]);
}
}
}
// cout<<f[S][0]<<" "<<g[S][0]<<" "<<h[S][0]<<endl;
}
}
ans=(h[all][0]*m%mod+g[all][0]*sum[n-2]%mod)%mod;
cout<<f[all][0]<<" "<<ans;
return 0;
}
B. T2 最简单辣快来做
由于模数不互质,不能提前预处理负幂次
考虑进行二维前缀和
把关键点形成的网格拿出来处理四个方向的前缀和,然后将询问点推到网格整点进行加减计算
注意预处理次方,否则得写光速幂
代码实现
#include<bits/stdc++.h>
using namespace std;
const int maxn=3005;
int n,t,ll,rr,mod,a,b,totx,toty,x[maxn],y[maxn],sum[maxn][maxn][4],h[maxn],px[maxn],py[maxn],xx,yy,lx[maxn],ly[maxn];
int pos[maxn][maxn];
int read(){
int x=0,f=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
while(isdigit(ch)){x=x*10+ch-48;ch=getchar();}
return x*f;
}
void modadd(int &a,int b){
a=(a+b)%mod;
return ;
}
int po(int a,int b){
if(b<0)return 0;
int ans=1;
while(b){
// cout<<a<<" "<<b<<endl;
if(b&1)ans=1ll*ans*a%mod;
a=1ll*a*a%mod;
b>>=1;
}
return ans;
}
int main(){
freopen("satellite.in","r",stdin);
freopen("satellite.out","w",stdout);
n=read(),t=read(),ll=read(),rr=read(),mod=read(),a=read(),b=read();
for(int i=1;i<=n;i++){
h[i]=read();
lx[i]=x[i]=read();
ly[i]=y[i]=read();
}
lx[n+1]=ll,ly[n+1]=rr;
sort(lx+1,lx+n+2);totx=unique(lx+1,lx+n+2)-lx-1;
sort(ly+1,ly+n+2);toty=unique(ly+1,ly+n+2)-ly-1;
for(int i=1;i<=n;i++){
x[i]=lower_bound(lx+1,lx+totx+1,x[i])-lx;
y[i]=lower_bound(ly+1,ly+toty+1,y[i])-ly;
modadd(pos[x[i]][y[i]],h[i]);
}
for(int i=1;i<=totx+1;i++)px[i]=po(a,lx[i]-lx[i-1]);
for(int i=1;i<=toty+1;i++)py[i]=po(b,ly[i]-ly[i-1]);
// cout<<"hhh "<<endl;
for(int i=1;i<=totx;i++){
for(int j=1;j<=toty;j++){
int res=0;
modadd(res,1ll*sum[i-1][j][0]*px[i]%mod);
modadd(res,1ll*sum[i][j-1][0]*py[j]%mod);
modadd(res,mod-1ll*sum[i-1][j-1][0]*px[i]%mod*py[j]%mod);
modadd(res,pos[i][j]);sum[i][j][0]=res;
}
}
for(int i=1;i<=totx;i++){
for(int j=toty;j>=1;j--){
int res=0;
modadd(res,1ll*sum[i-1][j][1]*px[i]%mod);
modadd(res,1ll*sum[i][j+1][1]*py[j+1]%mod);
modadd(res,mod-1ll*sum[i-1][j+1][1]*px[i]%mod*py[j+1]%mod);
modadd(res,pos[i][j]);sum[i][j][1]=res;
}
}
for(int i=totx;i>=1;i--){
for(int j=1;j<=toty;j++){
int res=0;
modadd(res,1ll*sum[i+1][j][2]*px[i+1]%mod);
modadd(res,1ll*sum[i][j-1][2]*py[j]%mod);
modadd(res,mod-1ll*sum[i+1][j-1][2]*px[i+1]%mod*py[j]%mod);
modadd(res,pos[i][j]);sum[i][j][2]=res;
}
}
for(int i=totx;i>=1;i--){
for(int j=toty;j>=1;j--){
int res=0;
modadd(res,1ll*sum[i+1][j][3]*px[i+1]%mod);
modadd(res,1ll*sum[i][j+1][3]*py[j+1]%mod);
modadd(res,mod-1ll*sum[i+1][j+1][3]*px[i+1]%mod*py[j+1]%mod);
modadd(res,pos[i][j]);sum[i][j][3]=res;
}
}
// for(int i=0;i<=3;i++)cout<<sum[2][2][i]<<" ";
// puts("");
while(t--){
xx=read(),yy=read();
int posx=lower_bound(lx+1,lx+totx+1,xx)-lx;
int posy=lower_bound(ly+1,ly+toty+1,yy)-ly;
int pox1=po(a,xx-lx[posx-1]),pox2=po(a,lx[posx]-xx),poy1=po(b,yy-ly[posy-1]),poy2=po(b,ly[posy]-yy),res=0;
modadd(res,1ll*pox1*poy1%mod*sum[posx-1][posy-1][0]%mod);
modadd(res,1ll*pox1*poy2%mod*sum[posx-1][posy][1]%mod);
modadd(res,1ll*pox2*poy1%mod*sum[posx][posy-1][2]%mod);
modadd(res,1ll*pox2*poy2%mod*sum[posx][posy][3]%mod);
printf("%d\n",res);
}
return 0;
}
C. T3 是我的你不要抢
考虑根号分治,大于 不超过 ,可以两两处理的总复杂度是 的,记忆化一下
其余的单次 处理即可
D. T4 显然也是我整的
神仙题,下次碰见还想不出来……
搬篇巨佬的题解:
其实不用用 ,直接小根堆维护即可
代码实现
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int maxn=2e5+5;
int n,m,x,sta[maxn],tp,t;
int read(){
int x=0,f=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
while(isdigit(ch)){x=x*10+ch-48;ch=getchar();}
return x*f;
}
priority_queue<int,vector<int>,greater<int> >q;
int gcd(int a,int b){return a==0?b:gcd(b%a,a);}
int solve(int n){
int res=0,g=0;
if(q.top()>n/2){
int nxt=2*q.top()-n;
n-=nxt;res+=nxt;
while(!q.empty())sta[++tp]=q.top(),q.pop();
while(tp)q.push(sta[tp--]-nxt);
}
while(!q.empty()&&q.top()<=n/2){
g=gcd(g,q.top());
q.pop();
}
while(!q.empty()&&q.top()+g<=n){
g=gcd(g,q.top());q.pop();
}
if(q.empty())return res+g;
int ans=g+n%g;
while(!q.empty())sta[++tp]=q.top(),q.pop();
while(tp)q.push(sta[tp--]+ans-n);
q.push(g);
return res+solve(ans);
}
signed main(){
freopen("graph.in","r",stdin);
freopen("graph.out","w",stdout);
t=read();
while(t--){
n=read(),m=read();
for(int i=1;i<=m;i++)x=read(),q.push(x);
printf("%lld\n",solve(n));
}
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】