求n个和为s的非负整数的最大中位数,巨简单,结果没看懂题
#include<bits/stdc++.h>
using namespace std;
int t,s,z,ans;
double n;
int main()
{
scanf("%d",&t);
for(int i=1;i<=t;i++)
{
scanf("%lf%d",&n,&s);
z=ceil(n/2); // 求出中位数是排第几的数,注意z一点要开long long,这样才能用向上取整函数
ans=s/(n-z+1); // 要求和不变而中位数最大,就要让中位数前面的数尽量小,都等于0,然后让中位数尽可能接近剩下的数的平均数,用s除以剩下的数,因为自动向下取整所以不用担心有偏差
printf("%d\n",ans); // 然后就完了,真的简单啊
}
return 0;
}
---------------------------------------------------------------------------------------------------------------------------------
#include<bits/stdc++.h>
using namespace std;
const int N=100005;
int n,q,aa,ans=0,l,r;
int a[2*N],s[N*2];
int main()
{
scanf("%d%d",&n,&q);
for(int i=1;i<=n;i++)
{
scanf("%d",&aa);
aa+=N; // a是读进来的数,为了防止有负数所以全部加上一个很大的数N
a[aa]++; // 该数的数量加一,用的是桶排
}
s[0]=0;
for(int i=1;i<2*N;i++) // 注意,这里要算的前缀和下标范围是整个数据范围,就是2N
{
s[i]=s[i-1]+a[i]; // 第i个前缀和等于第i-1个前缀和加上i的数量
}
for(int i=1;i<=q;i++)
{
ans=0;
scanf("%d%d",&l,&r);
l+=N; // 前面都加了N,所以这里的范围也要加N
r+=N;
ans=s[r]-s[l-1]; // l到r范围内的数等于第r个前缀和减去第l-1个前缀和,可以自己推理一下得到
printf("%d\n",ans);
}
return 0;
}
---------------------------------------------------------------------------------------------------------------------------------
如果两个质数的和为 s,那么他们的乘积最大值是多少
#include<bits/stdc++.h>
using namespace std;
int s,a,b;
long long m=1,n=0; // 乘积要开long long ,因为数据范围给到了1e5,int会爆
int k=1;
int z[2000000];
bool tf=true;
int main()
{
scanf("%d",&s);
for(int j=2;j<=s;j++) // 先找出s以内的质数,这样复杂度小一点
{
tf=true;
for(int i=2;i*i<=j;i++)
{
if(j%i==0)
{
tf=false;
break;
}
}
if(tf==true)
{
z[k]=j;
k++;
}
}
for(int a=1;a<k;a++) // 然后暴力枚举,如果相加等于s,就算出他们的乘积
{
for(int b=1;b<k;b++)
{
if(z[a]+z[b]==s) m=1ll*z[a]*z[b];
if(m>n) n=m; // 用n找出最大的乘积
}
}
printf("%lld",n); // 输出,记得是lld
return 0;
}
---------------------------------------------------------------------------------------------------------------------------------
#include<bits/stdc++.h>
using namespace std;
int n,k,lenmz,lenmf,lenc,ans=0;
char m[800];
char a;
int c[800],mf[800],mz[800];
bool tf;
int hw(int a[],int lena) // 写一个判断回文数的函数,往函数里传数组用的是int a[]的形式,同时要把长度传进去
{
int i=0;
tf=true;
lena--; // 数组从零开始,所以长度要减一才是最后一位数的下标
while(i<lena)
{
if(a[i]!=a[lena]) // 看最后一位和第一位的数字是否相等,不相等就不是回文数,可以停止循环,否则前后都往中间推进,继续进行比较
{
tf=false;
break;
}
else
{
i++;
lena--;
}
}
if(tf==true) return 1;
else return 0;
}
int main()
{
cin>>n;
scanf("%s",m); // 先以字符串的形式读入这个数字
lenmz=strlen(m); // 得到他的长度
lenmf=lenmz;
memset(c,0,sizeof(c));
memset(mf,0,sizeof(mf));
memset(mz,0,sizeof(mz));
for(int i=0;i<lenmf;i++)
{
if(m[i]>='0'&&m[i]<='9') mz[i]=m[i]-'0'; // 先处理10以内的数字
else mz[i]=m[i]-'a'+10; //因为10以上的数字以字母的形式出现,所以减去a的编码,然后加20让他成为一个两位数
}
if(hw(mz,lenmz)==1) // 引用上面写的函数,判断他是不是回文数,如果自己本身不是回文数才要进行后面的操作
{
for(int i=0;i<lenmf;i++)
{
printf("%d",mz[i]);
}
printf("\n0");
}
else while(hw(mz,lenmz)!=1)
{
memset(c,0,sizeof(c));
memset(mf,0,sizeof(mf));
ans++; //如果不是回文数,操作次数加1
for(int i=0;i<lenmz;i++)
{
mf[i]=mz[lenmz-i-1]; // 把他倒过来,然后进行高精加
}
lenc=0;
k=0;
while(lenc<lenmz)
{
c[lenc]=mz[lenc]+mf[lenc]+k;
k=c[lenc]/n;
c[lenc]%=n;
lenc++;
}
++lenc; // 位数相等时就停下了,可能在更高位上有进位
c[lenc-1]=k;
if(k==0) lenc--; // 如果最高位是0,删除最高位
for(int i=0;i<lenc;i++)
{
mz[i]=c[i]; // 再把加完的结果给回原来的数组
}
lenmz=lenc;
if(ans>30) break; // 操作次数大于30时马上停止,后面的操作没有意义了
}
if(ans<=30&&ans!=0)
{
for(int i=0;i<lenmz;i++)
{
if(mz[i]<=9) printf("%d",mz[i]); // 输出得到的最小回文数
else putchar('a'+mz[i]-10); // 大于10的数要用字符形式输出,原来-'a'+10,现在还原回去就是+'a'-10
}
printf("\n%d",ans); 然后输出操作次数
}
else printf("impossible"); // 不然输出给定字符
return 0;
}
总结:首先吧,考试要记得写文件输入输出,血的教训,然后要自己算一下复杂度,超时就完蛋,注意细节,要学会知识的迁移,不要把简单的东西复杂化,函数内传数组不需要写下标值域,还要算一下数据范围,看int会不会爆,不要老是忘long long,记得向上取整函数只对double有用