前言
rk44.如果T1 5min看出来能上榜1.
终于上紫了…
真.暴力出奇迹.
int T,a,b;
ll n,m,ans;
void calc(ll x) {
while(x) {
int y=x%10;
a=min(a,y);
b=max(b,y);
x/=10;
}
}
int main() {
qr(T); while(T--) {
qr(n); qr(m);
while(--m) {
a=9,b=0;
calc(n);
if(!a) break;
n+=a*b;
}
pr2(n);
}
return 0;
}
不会TLE的原因:9*9=81,所以k极大时百位一定会出现0,复杂度至多 .
赛时能想到这个AC方法是因为看到有人3min秒了,于是感觉是非常单纯的模拟(?).
一个块的大小必须
块内权值的最大值.
贪心起见,我们让块大小
权值最大值,这样即可分出尽量多的块.
同时,最优做法肯定是对排序后的权值不断取前缀组成块. 具体证明可以用微扰.
int T,n,a[N],ans,last;
int main() {
qr(T); while(T--) {
qr(n);for(int i=1;i<=n;i++) qr(a[i]);
sort(a+1,a+n+1); ans=last=0;
for(int i=1;i<=n;i++)
if(i-last>=a[i]) ans++,last=i;
pr2(ans);
}
return 0;
}
要满足
.
我们考虑计算对于每个
为定值时的方案数.
然后我们求一下后缀和即可.
int a,b,c,d;
ll v[N],s,ans;
int main() {
qr(a); qr(b); qr(c); qr(d);
for(int i=b+c;i>=a+b;i--) {
ll l=max(a,i-c),r=min(b,i-b);
ll L=max(b,i-b),R=min(c,i-a);
v[i]=min(r-l+1,R-L+1);
}
for(int i=b+c;i>=c;i--) {
if(i<=d)ans+=s;
s+=v[i];
}
pr2(ans);
return 0;
}
CF和AT最喜欢出构造题了.
这里有多种解法:
方法1
均值法
int n,m,a;
int main() {
qr(n); qr(m);
if((a=m/n)==1) puts("NO");
else {
puts("YES");
int b=m%n,i=1;
for(i=1;i<=b;i++) pr1(a+1);
for( ;i<=n;i++) pr1(a);
printf("\n%d\n",a-1);
}
return 0;
}
正确性证明:
.
当
时,序列有
,对于任意
.
否则,
方法2
基于前面的判断无解后,
证明:
方法3
官方题解: .
显然是个凸函数(OIer从来只猜结论,不证明)
int n,h[N],a,b,c;
ll ans=1e18;
ll calc(ll t) {
ll x=0,y=0;
for(int i=1;i<=n;i++)
if(h[i]<=t) x+=t-h[i];
else y+=h[i]-t;
ll s=0,z,res=0;
if(c<a+b) {
z=min(x,y);
s+=z*c;
x-=z; y-=z;
}
s+=x*a+y*b;
ans=min(ans,s);
return s;
}
int main() {
qr(n); qr(a); qr(b); qr(c);
int l=1e9,r=0,lmid,rmid,len;
for(int i=1;i<=n;i++) qr(h[i]),l=min(l,h[i]),r=max(r,h[i]);
while(r-l>3) {
len=r-l+1;
lmid=l+len/3;
rmid=r-len/3;
if(calc(lmid)<calc(rmid)) r=rmid-1;
else l=lmid+1;
}
while(l<=r) calc(l++);
pr2(ans);
return 0;
}
复杂度:
我们充分利用22次的机会.
每次把一堆质数的幂的乘积输出,如果gcd得到了对应的质数,那么我们就考虑增大质数的幂.
2的幂无法正确求出,但是实际上22>30/2,所以误差正常.
其余的<850的质数我们都可以认为可以求得正确的指数.
最后我们*2输出即可.
然后,我们考虑忽略掉的<850的质数的情况:
- ,合法.
- 质数,*2正好吻合.
- 质数*质数,实际最多 *4,误差允许.
- 质数* 质数*质数,显然不能再加质因数了(*2就爆了),所以输出2,实际为8,答案合法.
#include<map>
#include<set>
#include<queue>
#include<cmath>
#include<cstdio>
#include<vector>
#include<string>
#include<cstring>
#include<iostream>
#include<algorithm>
#define lc (x<<1)
#define rc (x<<1|1)
#define gc getchar()//(p1==p2&&(p2=(p1=buf)+fread(buf,1,size,stdin),p1==p2)?EOF:*p1++)
#define mk make_pair
#define pi pair<int,int>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int N=1e4+50,size=1<<20;
//char buf[size],*p1=buf,*p2=buf;
template<class o> void qr(o &x) {
char c=gc; x=0; int f=1;
while(!isdigit(c)){if(c=='-')f=-1; c=gc;}
while(isdigit(c)) x=x*10+c-'0',c=gc;
x*=f;
}
template<class o> void qw(o x) {
if(x/10) qw(x/10);
putchar(x%10+'0');
}
template<class o> void pr1(o x) {
if(x<0)x=-x,putchar('-');
qw(x); putchar(' ');
}
template<class o> void pr2(o x) {
if(x<0)x=-x,putchar('-');
qw(x); puts("");
}
bool v[N];
int prime[N],tot,T,ans,n;
struct node {
int x,y,z;//幂,指数,质数
bool operator <(node b) const {
return y==b.y?x>b.x:y<b.y;
}
}tmp,b[66];
priority_queue<node> q;
int main() {
n=N-5;
for(int i=2;i<=n;i++) if(!v[i]) {
prime[++tot]=i;
for(int j=i*i;j<=n;j+=i) v[j]=1;
}
qr(T); while(T--) {
while(!q.empty()) q.pop(); ans=1;
for(int i=1;i<=tot;i++) q.push((node){prime[i],1,prime[i]});
for(int j=1;j<=22;j++) {
ll x=1; int cnt=0;
while(!q.empty()) {
b[++cnt]=q.top();
if(1.0*x*b[cnt].x>=1e18) break;
q.pop(); x*=b[cnt].x;
}
printf("? %lld\n",x);
fflush(stdout);
qr(x);
for(int i=1;i<cnt;i++)
if(x%b[i].x==0) {
ans/=b[i].y;
b[i].y++;
ans*=b[i].y;
b[i].x*=b[i].z;
q.push(b[i]);
}
}
printf("! %d\n",ans*2);
}
return 0;
}