前言
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;
}