难受,炸\(long~long\),\(QwQ\)
\(prob1:Maximal~GCD\)
一句话:注意判炸\(long~long\)
没公约数的情况不用说了,若有设其为\(p\),很明显\(n\)为\(p\)的倍数,此时可以将序列的和化为\(n/p\)个\(p\)的和,又\(n/p\)个最少为\(k*(k+1)>>1\)个,所以就得到了\(n/p\)的下界,则\(p\)的上界为\(\frac{n}{k*(k+1)>>1}\),只需求在该界之下的最大的\(n\)的因数即可求出\(p\)的最大值。
\(tmp\)之下第一个\(n\)的倍数可以这么求:
inline long long chu(long long n,long long k)
{
long long g=1;
for(;n%k;k=n/k+g,g^=1);
return g?k:n/k;
}
总的代码:
#include<iostream>
using namespace std;
inline long long read()
{
long long x=0;
char ch=getchar();
for(;!isalnum(ch);ch=getchar());
for(;isalnum(ch);ch=getchar()) x=x*10+ch-'0';
return x;
}
inline long long need(long long m,long long f)
{
long long ans=2*m-f*f+f;
ans=ans/(2*f);
return ans;
}
inline long long chu(long long n,long long k)
{
long long g=1;
for(;n%k;k=n/k+g,g^=1);
return g?k:n/k;
}
int main()
{
// freopen("out.cpp","w",stdout);
long long n=read(),k=read();
long long tmp=need(n,k);
tmp=min(tmp,n/(k*(k+1)>>1));
if(tmp<=0||k>2e5) puts("-1"),exit(0);
long long p=chu(n,tmp);
long long t=n-(k*(k+1)>>1)*p;
for(long long j=1;j<=k-1;++j) printf("%lld ",p*j);
printf("%lld\n",t+k*p);
return 0;
}
\(prob2:Artem~and~Array\)
明显易知,在一个\(2* 2\)的矩阵中,若存且仅存在一个\("* "\),那么,这个\("* "\)必须变成".",\(bfs\)一下就好了
#include<iostream>
#include<cstdio>
#include<queue>
using namespace std;
#define in read()
#define re register
#define fur(i,a,b) for(re int i=a;i<=b;++i)
#define fdr(i,a,b) for(re int i=a;i>=b;--i)
#define jinitaimei signed
#define nm make_pair
#define pr pair<int,int>
//#define int long long
inline int read()
{
int x=0;
char ch=getchar();
for(;!isalnum(ch);ch=getchar());
for(;isalnum(ch);ch=getchar()) x=x*10+ch-'0';
return x;
}
const int xx=2e3+10;
int wall[xx][xx];
int n,m,name=0;
char op[xx];
queue<pr>q;
inline void bfs()
{
while(!q.empty())
{
int x=q.front().first,y=q.front().second;
q.pop();
name=wall[x+1][y+1]+wall[x][y+1]+wall[x+1][y];
if(name==1&&y<m&&x<n)
{
if(wall[x+1][y+1]) wall[x+1][y+1]=0,q.push(nm(x+1,y+1));
if(wall[x+1][y]) wall[x+1][y]=0,q.push(nm(x+1,y));
if(wall[x][y+1]) wall[x][y+1]=0,q.push(nm(x,y+1));
}
name=wall[x+1][y-1]+wall[x][y-1]+wall[x+1][y];
if(name==1&&y>1&&x<n)
{
if(wall[x+1][y-1]) wall[x+1][y-1]=0,q.push(nm(x+1,y-1));
if(wall[x+1][y]) wall[x+1][y]=0,q.push(nm(x+1,y));
if(wall[x][y-1]) wall[x][y-1]=0,q.push(nm(x,y-1));
}
name=wall[x-1][y+1]+wall[x][y+1]+wall[x-1][y];
if(name==1&&x>1&&y<m)
{
if(wall[x-1][y+1]) wall[x-1][y+1]=0,q.push(nm(x-1,y+1));
if(wall[x-1][y]) wall[x-1][y]=0,q.push(nm(x-1,y));
if(wall[x][y+1]) wall[x][y+1]=0,q.push(nm(x,y+1));
}
name=wall[x-1][y-1]+wall[x-1][y]+wall[x][y-1];
if(name==1&&x>1&&y>1)
{
if(wall[x-1][y-1]) wall[x-1][y-1]=0,q.push(nm(x-1,y-1));
if(wall[x-1][y]) wall[x-1][y]=0,q.push(nm(x-1,y));
if(wall[x][y-1]) wall[x][y-1]=0,q.push(nm(x,y-1));
}
}
}
jinitaimei main()
{
n=in,m=in;
fur(i,1,n)
{
scanf("%s",op);
fur(j,1,m)
{
wall[i][j]=op[j-1]=='*'?1:0;
if(!wall[i][j]) q.push(nm(i,j));
}
}
bfs();
fur(i,1,n)
{
fur(j,1,m) printf("%c",wall[i][j]?'*':'.');
cout<<endl;
}
return 0;
}
\(prob3:Students'~Revenge\)
若将所有任务按\(b\)为第一关键字排序,那么主席肯定会选我们选中的\(p\)个任务中的靠后\(k\)个,先得到这后\(k\)个\(\sum a\)的最大值,再在前面\(p-k\)个中取到\(max(\sum b)\)即可
#include<iostream>
#include<ext/pb_ds/priority_queue.hpp>
using namespace std;
#define in read()
#define re register
#define fur(i,a,b) for(re int i=a;i<=b;++i)
#define fdr(i,a,b) for(re int i=a;i>=b;--i)
#define int long long
#define pr pair<int,int>
#define hp __gnu_pbds::priority_queue<pr,greater<pr> >
#define nm make_pair
hp q;
inline int read()
{
int x=0;
char ch=getchar();
for(;!isalnum(ch);ch=getchar());
for(;isalnum(ch);ch=getchar()) x=x*10+ch-'0';
return x;
}
const int xx=1e5+10;
struct person
{
int a,b;
int id;
}m[xx];
bool choose[xx];
inline bool cmp(person x,person y)
{
return (x.b^y.b)?(x.b<y.b):(x.a>y.a);
}
main()
{
int n=in,l=in,k=in,Min=n-k+1;
fur(i,1,n) m[i].a=in,m[i].b=in,m[i].id=i;
sort(m+1,m+n+1,cmp);
fdr(i,n,n-k+1) choose[i]=true,q.push(nm(m[i].a,i));
l=l-k;
fdr(i,n-k,l+1) if(m[i].a>q.top().first)
{
choose[q.top().second]=false;
q.pop();
q.push(nm(m[i].a,i));
Min=i;
}
while(!q.empty()) printf("%lld ",m[q.top().second].id),q.pop();
while(l--) printf("%lld ",m[--Min].id);
puts("");
return 0;
}
\(prob4:Ball~Coloring\)
先令所有二元组的\(x\)小于\(y\),在两边得到\(Rmax,Rmin,Lmax,Lmin\),此为第一种情况,
再将序列按\(x\)为关键字排序,从小到大除最大的\(x\)所在的二元组外,其他二元组一一交换,可以证明,答案一定在其中
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define in read()
#define re register
#define fur(i,a,b) for(re int i=a;i<=b;++i)
#define fdr(i,a,b) for(re int i=a;i>=b;--i)
#define cl(a,b) memset(a,b,sizeof(a))
#define jinitaimei signed
#define int long long
inline int read()
{
int x=0;
char ch=getchar();
for(;!isalnum(ch);ch=getchar());
for(;isalnum(ch);ch=getchar()) x=x*10+ch-'0';
return x;
}
const int xx=2e5+101;
struct person
{
int x,y;
}m[xx];
inline bool cmp(person a,person b)
{
return a.x<b.x;
}
jinitaimei main()
{
int n=in,xmax=0,xmin=2e18,ymax=0,ymin=2e18;
fur(i,1,n)
{
m[i].x=in,m[i].y=in;
if(m[i].x>m[i].y) swap(m[i].x,m[i].y);
xmax=max(xmax,m[i].x);
xmin=min(xmin,m[i].x);
ymax=max(ymax,m[i].y);
ymin=min(ymin,m[i].y);
}
int ans=(xmax-xmin)*(ymax-ymin);
sort(m+1,m+n+1,cmp);
ymin=xmin;
int maxl=m[1].y,minl=m[1].y,ans2=2e18;
fur(i,2,n-1)
{
maxl=max(maxl,m[i].y);
minl=min(minl,m[i].y);
ans2=min(ans2,max(maxl,m[n].x)-min(minl,m[i+1].x));
}
if(n>2) ans2*=(ymax-ymin);
ans=min(ans,ans2);
cout<<ans<<endl;
return 0;
}
\(prob5:Ant~Man\)
可以证明,将从\(1\)到\(n\)的所有非\(s\)或\(t\)的点局部最优地插入\(s\)与\(t\)的间隔中可以得到全局最优解
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
#define in read()
#define re register
#define fur(i,a,b) for(re int i=a;i<=b;++i)
#define fdr(i,a,b) for(re int i=a;i>=b;--i)
#define cl(a,b) memset(a,b,sizeof(a))
#define jinitaimei signed
#define int long long
inline int read()
{
int x=0;
char ch=getchar();
for(;!isalnum(ch);ch=getchar());
for(;isalnum(ch);ch=getchar()) x=x*10+ch-'0';
return x;
}
const int xx=5e3+101;
int nxt[xx];
int x[xx],a[xx],b[xx],c[xx],d[xx];
inline int dis(int xa,int ya)
{
if(ya<xa) return x[xa]-x[ya]+c[xa]+b[ya];
return x[ya]-x[xa]+d[xa]+a[ya];
}
jinitaimei main()
{
int n=in,s=in,t=in;
fur(i,1,n) x[i]=in;
fur(i,1,n) a[i]=in;
fur(i,1,n) b[i]=in;
fur(i,1,n) c[i]=in;
fur(i,1,n) d[i]=in;
nxt[s]=t;nxt[t]=0;
int ans=dis(s,t);
fur(i,1,n) if(i!=s&&i!=t)
{
int mn=2e18,tmp=s,j=s;
while(nxt[j])
{
if(dis(j,i)+dis(i,nxt[j])-dis(j,nxt[j])<=mn)
{
mn=dis(j,i)+dis(i,nxt[j])-dis(j,nxt[j]);
tmp=j;
}
j=nxt[j];
}
ans+=mn;
nxt[i]=nxt[tmp];
nxt[tmp]=i;
}
printf("%lld\n",ans);
return 0;
}
原文地址:https://www.cnblogs.com/ALANALLEN21LOVE28/p/11502657.html
时间: 2024-10-14 20:34:58