11.20 NOIP2024模拟赛#25 div1
挂分力
T1
发现单点修更优,于是就成了拓欧板子
因为对于通解 \(x',y'\) 有通式:\(a(x+qb)+b(y-qa)=d\)
即求 \(\min\{|x+qb|+|y-qa|\}\)
然后考虑 \(q\) 在哪能取到最小
推出来了两个值,直接代,过掉了样例
然鹅这两个值有向上/下取整之分,所以需要代四个值
然后就 \(100 \rightarrow 80\)
赛后改一下就过了
点击查看代码
#include<bits/stdc++.h>
#define int long long
#define ll long long
#define fd(i,a,b) for(int i=(a);i<=(b);i=-~i)
#define bd(i,a,b) for(int i=(a);i>=(b);i=~-i)
#define db(x) cout<<"DEBUG "<<#x<<" = "<<x<<endl;
#define endl '\n'
using namespace std;
//#define SIZE (1<<20)
//char In[SIZE],Out[SIZE],*p1=In,*p2=In,*p3=Out;
//#define getchar() (p1==p2&&(p2=(p1=In)+fread(In,1,SIZE,stdin),p1==p2)?EOF:*p1++)
template<typename _T=int>
inline _T read()
{
_T x=0,f=1;char c=getchar();
while(c<'0'||c>'9'){if(c=='-') f=-1;c=getchar();}
while(c>='0'&&c<='9'){x=x*10+(c-48);c=getchar();}
return x*f;
}
const int N=1e6+509,M=1e6+509,mod=998244353,inf=0x3f3f3f3f;
int n,a,b,v[N],ans;
pair<int,int> exgcd(int x,int y,int &d)
{
if(!y) {d=x;return {1,0};}
auto t=exgcd(y,x%y,d);
return {t.second,t.first-x/y*t.second};
}
signed main()
{
#define FJ
#ifdef FJ
freopen("tease.in","r",stdin);
freopen("tease.out","w",stdout);
#else
// freopen("ex_tease6.in","r",stdin);
// freopen("tease.out","w",stdout);
#endif
//#define io
#ifdef io
ios::sync_with_stdio(0);
cin.tie(0); cout.tie(0);
#endif
n=read(),a=read(),b=read();
if(a<b) swap(a,b);
fd(i,1,n) v[i]=abs(read());
fd(i,1,n)
{
int c=v[i],x,y,d;
auto s=exgcd(a,b,d);
x=s.first,y=s.second;
if(c%d!=0)
{
puts("-1");
return 0;
}
int xx=x*c/d,yy=y*c/d,dx=b/d,dy=a/d;
int s1=ceil(double(-xx+1)/double(dx)),s2=floor(double(yy-1)/double(dy)),s3=floor(double(-xx+1)/double(dx)),s4=ceil(double(yy-1)/double(dy));
ans+=min({abs(s1*dx+xx)+abs(yy-s1*dy),abs(s2*dx+xx)+abs(yy-s2*dy),abs(s3*dx+xx)+abs(yy-s3*dy),abs(s4*dx+xx)+abs(yy-s4*dy),(c%a==0)?c/a:inf,(c%b==0)?c/b:inf});
}
printf("%lld\n",ans);
return 0;
}
T2
一看 \(n=2\),这不是小凯的疑惑?
然后码了个 \(n=1\),\(n=2\),\(m \le 5\times 10^3\) 的
然后尝试测一下大样例
发现最小值一般很小,然后猜到答案不会很大
于是假设 \(m\) 的上限是 \(a_1\times a_2 - a_1 -a_2\)
然后多拿了 \(24\) 分
赛后发现这并不是上限,我假设的上限小了,开大一点可以再多拿 \(8\) 分
然后 \(n=2\) 时没有判 \((a_1,a_2)\) 不为 \(1\) 的情况,丢 \(4\) 分
这样算下来,其实可以有 \(72\) 分的
正解是同余最短路,因为 \(a_1\) 很小,所以复杂度是“能过”
点击查看代码
#include<bits/stdc++.h>
#define int long long
#define ll long long
#define fd(i,a,b) for(int i=(a);i<=(b);i=-~i)
#define bd(i,a,b) for(int i=(a);i>=(b);i=~-i)
#define db(x) cout<<"DEBUG "<<#x<<" = "<<x<<endl;
#define endl '\n'
using namespace std;
//#define SIZE (1<<20)
//char In[SIZE],Out[SIZE],*p1=In,*p2=In,*p3=Out;
//#define getchar() (p1==p2&&(p2=(p1=In)+fread(In,1,SIZE,stdin),p1==p2)?EOF:*p1++)
template<typename _T=int>
inline _T read()
{
_T x=0,f=1;char c=getchar();
while(c<'0'||c>'9'){if(c=='-') f=-1;c=getchar();}
while(c>='0'&&c<='9'){x=x*10+(c-48);c=getchar();}
return x*f;
}
const int N=1e6+509,M=1e6+509,mod=998244353;
uint64_t PRG_state;
uint64_t get_number()
{
PRG_state^=PRG_state<<13;
PRG_state^=PRG_state>>7;
PRG_state^=PRG_state<<17;
return PRG_state;
}
int readW(int l,int r)
{
return get_number()%(r-l+1)+l;
}
int n,lim,m;
int a[N];
inline void init()
{
n=read(),lim=read(),m=read(),PRG_state=read<uint64_t>();
fd(i,1,n) a[i]=readW(2,lim);
}
namespace SubI
{
void Main()
{
if(n==1)
{
if(m%a[1]) printf("%lld",m);
else printf("%lld",m-1);
exit(0);
}
if(n==2)
{
int g=__gcd(a[1],a[2]);
if(g==1) printf("%lld",a[1]*a[2]-a[1]-a[2]);
else printf("%lld",(ll)1e18-(m%g==0));
exit(0);
}
}
}
namespace SubII
{
int d[M],mn,len,e[N],ans,num[N];
bool vis[M];
void dij()
{
memset(d,10,sizeof(d));
memset(vis,0,sizeof(vis));
d[0]=0;
priority_queue< pair<int,int> > q;
q.push({0,0});
while(!q.empty())
{
int x=q.top().second;q.pop();
if(vis[x]) continue;
vis[x]=1;
fd(i,1,len)
{
int y=(x+e[i])%mn;
if(d[y]<=d[x]+e[i]) continue;
d[y]=d[x]+e[i];
q.push({-d[y],y});
}
}
}
inline void Main()
{
mn=a[1];
memset(num,10,sizeof(num));
fd(i,1,n) if(a[i]%mn) num[a[i]%mn]=min(num[a[i]%mn],a[i]);
fd(i,1,mn-1) if(num[i]<=1e8) e[++len]=num[i];
dij();
fd(i,1,mn-1)
{
if(d[i]<=m) ans=max(ans,d[i]-mn);
else
{
int k=(d[i]-m-1)/mn+1;
ans=max(ans,d[i]-k*mn);
}
}
printf("%lld",ans);
}
}
signed main()
{
#define FJ
#ifdef FJ
freopen("doubt.in","r",stdin);
freopen("doubt.out","w",stdout);
#else
// freopen("doubt1.in","r",stdin);
// freopen("doubt.out","w",stdout);
#endif
//#define io
#ifdef io
ios::sync_with_stdio(0);
cin.tie(0); cout.tie(0);
#endif
init();
sort(a+1,a+n+1);
n=unique(a+1,a+n+1)-a-1;
if(n<=2) SubI::Main();
else SubII::Main();
return 0;
}
T3
题都没看懂……
正解是注意到状态数很少
然后跑容斥 DP 即可
看 T4 了
T4
一眼 Trie,然后可以莫队维护
但是我忘了怎么删数,然后就码的离线+Trie
然后拿到 \(40\) 分
正解是莫二离……
总结
- T1 挂
- T2 挂
- 莫队需要巩固一下
- “注意到”
本文来自博客园,作者:whrwlx,转载请注明原文链接:https://www.cnblogs.com/whrwlx/p/18563516