看看蒟蒻交了一版才调完
A
Idea
一道十分简单的题
只需要在奇数点是判断下当前字符是否等于下一个字符
- 是。记录并修改
- 否。跳过
Code
int n,ans;
char s[maxn];
signed main(){
n=read(); scanf("%s",s+1);
for(int i=1;i<=n;i+=2){
if(s[i]==s[i+1]){
ans++;
if(s[i+1]=='b') s[i]='a';
else s[i]='b';
}
}
printf("%d
",ans);
printf("%s",s+1);
return 0;
}
B
Idea
考场上看到样例解释,他是从大的数开始算的。
于是,我就排了个序。然后照着他的计算方法计算(ans)
序列随便输出,然后。。。我就过了
Code
struct Node{
int id,val;
inline bool operator<(const Node&x)const{return val>x.val;}
}sum[maxn];
int ans;
signed main(){
int n=read();
for(int i=1;i<=n;i++){
sum[i].val=read();
sum[i].id=i;
}
sort(sum+1,sum+n+1);
for(int i=1;i<=n;i++)
ans+=(i-1)*sum[i].val+1;
printf("%d
",ans);
for(int i=1;i<=n;i++)
printf("%d ",sum[i].id);
return 0;
}
C
Idea
一道恶心的模拟,除了(if;else)就没啥了。看代码比较好理解,虽然我没有注释
Code
signed main(){
int x1,y1,x11,y11;
int x2,y2,x22,y22;
int x3,y3,x33,y33;
int xr,yr,xrr,yrr;
cin>>x1>>y1>>x11>>y11;
cin>>x2>>y2>>x22>>y22;
cin>>x3>>y3>>x33>>y33;
if(x2<=x1&&x22>=x11){
if(y2<= y1){
if(y22>=y11) puts("NO");
else
if(x3<=x1&&x33>=x11&&(y3<=y22||y3<=y1)&&y33>=y11) puts("NO");
else puts("YES");
}else{
if(y22>=y11){
if(x3<=x1&&x33>=x11&&y3<=y1&&(y33>=y2||y33>=y11)) puts("NO");
else puts("YES");
}else{
if(x3<=x1&&x33>=x11&&y3<=y1&&y33>=y11) puts("NO");
else puts("YES");
}
}
}else{
if(y2<=y1&&y22>=y11){
if(x2<=x1)
if(y3<=y1&&y33>=y11&&(x3<=x22||x3<=x1)&&x33>=x11) puts("NO");
else puts("YES");
else{
if(x22>=x11)
if(y3<=y1&&y33>=y11&&(x33>=x2||x33>=x11)&&x3<=x1) puts("NO");
else puts("YES");
else
if(x3<=x1&&x33>=x11&&y3<=y1&&y33>=y11) puts("NO");
else puts("YES");
}
}else
if(x3<=x1&&x33>=x11&&y3<=y1&&y33>=y11) puts("NO");
else puts("YES");
}
return 0;
}
D
Idea
需要用到(Gcd),因为要求(n)个数的最大公约数,比(C)题还水
注意(Gcd=0),开(long;long)就好了(sim)
Code
inline int gcd(int a,int b){
if(b==0) return a;
return gcd(b,a%b);
}
int n,a[maxn],b[maxn];
signed main(){
n=read();
for(int i=0;i<n;i++)
a[i]=read();
sort(a,a+n);
for (int i=1;i<n;i++)
b[i]=a[i]-a[i-1];
int ans=b[0];
for(int i=1;i<n;i++)
ans=gcd(ans,b[i]);
int sum=0;
for(int i=0;i<n;i++)
sum+=abs(a[n-1]-a[i]);
cout<<sum/ans<<' '<<ans;
return 0;
}
E1
Idea
这道题。。。(POJ)上有。。。。
我在这里放个博客链接
再放上我的代码
Code
unsigned int sum[40000];
int T,n;
inline void play_table(){
unsigned int pre=1,nw;
sum[1]=1;
for(int i=2;i<=32000;++i){
nw=pre+(int)log10((double)i)+1;
sum[i]=sum[i-1]+nw;
pre=nw;
}
}
inline int getd(int x){
int k1;
for(int i=1;i<=32000;++i)
if(x<=sum[i]){
k1=i;
break;
}
int p=x-sum[k1-1],len=0,i;
for(i=1;i<=k1;++i){
len+=(int)log10((double)i)+1;
if(p<=len)
break;
}
int ilen=(int)log10((double)i)+1;
len-=ilen;
int k2=p-len;
for(int j=k2+1;j<=ilen;++j)
i/=10;
return i%10;
}
signed main(){
play_table();
T=read();
while(T--){
n=read();
printf("%lld
",getd(n));
}
return 0;
}
E2
Idea
(E1) 是(int)范围,(E2)是(long;long)范围
这里我用到二分来解决,不多,也就三四十行
Code
inline int countDigits(int n){//数字位数
int cnt=0;
while(n>0){
n/=10;
cnt++;
}
return cnt;
}
inline int getPos(int a){
int l=countDigits(a);
int res=0;
for(int i=0;i<l-1;i++)
res=res*10+9;
int offset=0;
int prev=a,curr=res;
int ans=0;
while(prev>0){
int d=prev-curr;
ans+=(d*(d+1)/2+offset*d)*l;
offset+=d;
l--;
prev=curr;
curr/=10;
}
return ans;
}
inline int getPosv2(int a){
int l=countDigits(a);
int res=0;
for(int i=0;i<l-1;i++)
res=res*10+9;
int prev=a,curr=res;
int ans=0;
while(prev>0){
ans+=(prev-curr)*l;
l--;
prev=curr;
curr/=10;
}
return ans;
}
int k;
signed main(){
int T=read();
while(T--){
int k=read();
int l=1,r=1e9;
while(l<r){
int mid=(l+r+1)>>1;//(l+r+1)/2;
int val=getPos(mid);
if(val>k) r=mid-1;
else l=mid;
}
int d=k-getPos(l);
if(d==0){
cout<<l%10<<endl;
continue;
}
r=l+1,l=1;
while(l<r){
int mid=l+r>>1; //l+r/2;
int val=getPosv2(mid);
if(val<d) l=mid+1;
else r=mid;
}
int z=getPosv2(l)-d;
int ans=0;
while(z>=0){
ans=l%10;
l/=10;
z--;
}
cout<<ans<<endl;
}
return 0;
}
F
Idea
这里我用的是(DP)
这一题其实观察题目的性质,选择位置 (i) 的代价为
(i),也就是说代价随着位置增加
发现到这里有单调性,考虑利用单调性 (DP)
设 (f[i]) 表示把 (1) 到 (i) 覆盖的最小代价
然后预处理出 (g[i]) 表示从 (i) 位置往右的第一个 (1) 的位置
(g) 的预处理显然,考虑 (f[i]) 怎么转移
首先我们可以选择 (i) 位置,那么转移显然
然后考虑 (i) 本身不选,选择一个位置(j) ,使得 (j) 能够覆盖 (i)
显然我们考虑选择的位置为 (g[i−k]) (这里先不考虑 (i−k<1) 的情况)
意思就是说,选择位置 (i−k) 往右的第一个 (1) 位置(也就是最左边能够覆盖 (i) 的 (1))
我们设这个位置为 (c),考虑选择位置 (c) 的最小花费,因为 (f) 单调不减,最小花费即为 (f[c−k−1]+c)
发现其实我们直接贪心地选择位置 (c) 一定比选择 (c) 后面的某个 (1) 更优
因为考虑后面位置代价,首先选后面本身位置的代价就比选 (c) 大,其次选后面的话,我们最优的(f)也会变大
所以后面的一定不如位置 (c),我们直接选择位置 (c) 转移即可
记住开(long ; long),否则就挂
Code
int f[maxn],dp[maxn];
char s[maxn];
int n,k;
signed main(){
n=read(); k=read();
scanf("%s",s+1);
f[n+1]=3*n;
for(int i=n;i>=1;i--) f[i]=s[i]=='1'?i:f[i+1];
dp[0]=0;
for(int i=1;i<=n;i++){
dp[i]=dp[i-1]+i;
int cnt=f[max(i-k,1ll)];
if(cnt<=i+k)
dp[i]=min(dp[i],dp[max(cnt-k,1ll)-1]+cnt);
}
printf("%lld",dp[n]);
return 0;
}
不要问图片为什么这么快,我也不知道
( ext{千万不要对任何事感到后悔,因为它曾经一度就是你想要的.后悔没用,要么忘记,要么努力})