题目链接 http://acm.zju.edu.cn/onlinejudge/showContestProblems.do?contestId=378
没有solution的题目待补
A
暴力
无技巧
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int debug_num=0;
#define debug cout<<"debug "<<++debug_num<<" :"
const int inf=2e9+10;
const int maxn=1e5+10;
int a[maxn];
int main()
{
//freopen("in.txt","r",stdin);
ios::sync_with_stdio(false);
int t;
cin>>t;
while(t--)
{
int n;
cin>>n;
for(int i=0;i<n;++i)
cin>>a[i];
int maxx=a[0];
int ans=0;
for(int i=1;i<n;++i){
if(a[i]>maxx){
maxx=a[i];
ans=i;
}
}
if(ans==0||ans==n-1) cout<<"No"<<endl;
else{
int flag=1;
for(int i=0;i<ans;++i){
if(a[i]>=a[i+1]) {
cout<<"No"<<endl;
flag=0;
break;
}
}
if(flag==0) continue;
for(int i=ans;i<n-1;++i){
if(a[i]<=a[i+1]) {
cout<<"No"<<endl;
flag=0;
break;
}
}
if(flag) cout<<"Yes"<<endl;
}
}
return 0;
}
B
做差,用数组做桶计数
注意做个差值shift,使得下标在合适区间
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int debug_num=0;
#define debug cout<<"debug "<<++debug_num<<" :"
const int maxn=1e5+10;
int n;
int a[maxn];
int b[maxn];
int c[maxn*4];
int main()
{
//freopen("in.txt","r",stdin);
ios::sync_with_stdio(false);
int t;
cin>>t;
while(t--)
{
memset(c,0,sizeof(c));
int n;
cin>>n;
for(int i=0;i<n;++i){
cin>>a[i];
}
for(int i=0;i<n;++i){
cin>>b[i];
}
for(int i=0;i<n;++i){
c[a[i]+(int)2e5-b[i]]++;
}
sort(c,c+4*maxn);
cout<<c[4*maxn-1]<<endl;
}
return 0;
}
C
D
E
F
观察上式,当p最小,a最大时,分母取值最大,为30。
对a数组进行sort,之后可将a分段,最多30段,每一段都除以相同的数值
如何分段呢?二分
分好段后,需要快速求得段内除以这个数的下取整和值
对sort后的a数组预处理前缀和即可,由于除数最大30,要开30维
时间复杂度 O(m∗logn∗logamaxp+nlogn) O ( m ∗ l o g n ∗ l o g p a m a x + n l o g n ) 其中 m m 为查询次数,为每一次二分的复杂度, logamaxp l o g p a m a x 为二分次数。 nlogn n l o g n 为一次排序的复杂度
数据量超过1e6使用快读是个好习惯
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int debug_num=0;
#define debug cout<<"debug "<<++debug_num<<" :"
const int mod=1e9;
const int maxn=5e5+10;
int read()
{
char ch='*';
while(!isdigit(ch=getchar()));//不是数字读掉
int num=ch-'0';
while(isdigit(ch=getchar())) num=num*10+ch-'0';
return num;
}
int pre[31][maxn];
int a[maxn];
int p[maxn];
int n,m;
void init()
{
//求出pre /1,/2,/30的前缀和
//memset(pre,0,sizeof(pre));
for(int chu=1;chu<=30;++chu){
pre[chu][0]=0;
}
for(int chu=1;chu<=30;++chu){
for(int i=1;i<=n;++i){
pre[chu][i]=(pre[chu][i-1]+a[i]/chu)%mod;
}
}
}
int main()
{
//freopen("in.txt","r",stdin);
int t;
scanf("%d",&t);
while(t--)
{
//cin>>n>>m;//n个数字 m个p
//cout<<n<<" "<<m<<endl;
scanf("%d %d",&n,&m);
for(int i=1;i<=n;++i) a[i]=read();
for(int i=1;i<=m;++i) p[i]=read();
// for(int i=1;i<=n;++i) cin>>a[i];
// for(int i=1;i<=m;++i) cin>>p[i];
//debug<<"*****************"<<endl;
ll ans=0;
sort(a+1,a+1+n);
init();
// for(int i=1;i<=n;++i){
// cout<<a[i]<<" ";
// }
// cout<<endl;
for(int i=1;i<=m;++i){//对于每个询问 log 的底数为p[i]
//debug<<"第"<<i<<"次询问:"<<endl;
ll sum=0;
//除1的在 1~p 之间
//除2的在p+1 ~p^2 之间
//...
//除30的在p^29+1 ~ p^30
ll now_p=p[i];
int id1=1;//id1左边界 id2右边界
int id2;
int chu=1;
while(1){
id2=upper_bound(a+1+(id1-1),a+1+n,now_p)-a-1;//返回小于等于now_p的最后一个数
//debug<<"id1 id2 now_p chu "<<id1<<" "<<id2<<" "<<now_p<<" "<<chu<<endl;
if(id2>=id1) sum=(sum+pre[chu][id2]-pre[chu][id1-1]+mod)%mod;//,cout<<"***"<<pre[chu][id2]-pre[chu][id1-1]<<endl
id1=id2+1;//下一次的左边界一定是上一次右边界的下一个
now_p=now_p*p[i];
chu++;
if(id2>=n) break;
}
ans=(ans+((i*sum)%mod))%mod;
}
printf("%lld\n",ans);
}
return 0;
}
G
H
I
一定可以产生 n(n−1)/2 n ( n − 1 ) / 2 个点
策略如下图,分情况讨论即可
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int debug_num=0;
#define debug cout<<"debug "<<++debug_num<<" :"
int main()
{
//freopen("in.txt","r",stdin);
ios::sync_with_stdio(false);
int t;
cin>>t;
while(t--)
{
int n;
cin>>n;
if(n%2==0){
for(int i=0;i<=n-3;++i){
if(i%2==0){
cout<<i<<" "<<2*n-2-i-1<<" ";
}
else cout<<i<<" "<<2*n-2-i+1<<" ";
}
cout<<n-2<<" "<<n<<" ";
cout<<n-1<<" "<<2*n-1<<endl;
}
else{
//奇数
//0~n-1
for(int i=0;i<=n-2;++i){
if(i%2==0){
cout<<i<<" "<<2*n-2-i-1<<" ";
}
else cout<<i<<" "<<2*n-2-i+1<<" ";
}
cout<<n-1<<" "<<2*n-1<<endl;
}
}
return 0;
}
J
贪心
考虑只要能将所有宝贝数量恰好分半到两个组即可。因为一旦这件事能完成,男女性别一定不是问题,题目说明可以有组为空
下面考虑如何将宝贝恰好分半
首先当 n%4==1||2 n % 4 == 1 | | 2 的 时候一定无解
当 n%4==0 n % 4 == 0 时,很好分两半,即首位依次配对
当 n%4==3 n % 4 == 3 时,对于前面一样做,对于最后三个人,价值分别为n-2,n-1,n
将n-2和n两个人分到有(n-1)/2的那组去
将(n-1)/2换到另外一组,n-1也放到该组即可
if写了100多行 太丑了
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int debug_num=0;
#define debug cout<<"debug "<<++debug_num<<" :"
const int maxn=1e5+10;
char ans[maxn];
char s[maxn];
int main()
{
//freopen("in.txt","r",stdin);
ios::sync_with_stdio(false);
int t;
cin>>t;
while(t--)
{
memset(ans,0,sizeof(ans));
memset(s,0,sizeof(s));
int n;
cin>>n;
for(int i=1;i<=n;++i){
cin>>s[i];
}
if(n%4==1||n%4==2){
cout<<-1<<endl;
continue;
}
if(n%4==0){
for(int i=1;i<=n;++i){
if(i%4==0||i%4==1){
if(s[i]=='1'){
ans[i]='3';
}
else{
ans[i]='1';
}
}
else{
if(s[i]=='1'){
ans[i]='4';
}
else{
ans[i]='2';
}
}
}
for(int i=1;i<=n;++i){
cout<<ans[i];
}
cout<<endl;
}
else{
if(n<4){
//cout<<n<<"***"<<endl;
if(s[1]=='1') ans[1]='3';
else ans[1]='1';
if(s[2]=='1') ans[2]='3';
else ans[2]='1';
if(s[3]=='1') ans[3]='4';
else ans[3]='2';
for(int i=1;i<=n;++i){
cout<<ans[i];
}
cout<<endl;
}
else{
int ahu=0;
for(int i=1;i<=n-3;++i){
if(i==(n-1)/2) ahu=(n-1)/2;
if(i%4==0||i%4==1){
if(s[i]=='1'){
ans[i]='3';
}
else{
ans[i]='1';
}
}
else{
if(s[i]=='1'){
ans[i]='4';
}
else{
ans[i]='2';
}
}
}
//ahu是特殊元素
if(ahu%4==0||ahu%4==1){//这种情况ahu现在被放在1,3 ,将其改为2,4
if(s[ahu]=='1') ans[ahu]='4';
else ans[ahu]='2';
if(s[n-1]=='1') ans[n-1]='4';
else ans[n-1]='2';
if(s[n-2]=='1') ans[n-2]='3';
else ans[n-2]='1';
if(s[n]=='1') ans[n]='3';
else ans[n]='1';
}
else{//这种情况ahu现在被放在2,4,将其改为1,3
if(s[ahu]=='1') ans[ahu]='3';
else ans[ahu]='1';
if(s[n-1]=='1') ans[n-1]='3';
else ans[n-1]='1';
if(s[n-2]=='1') ans[n-2]='4';
else ans[n-2]='2';
if(s[n]=='1') ans[n]='4';
else ans[n]='2';
}
for(int i=1;i<=n;++i){
cout<<ans[i];
}
cout<<endl;
}
}
}
return 0;
}
K
L
水题
无技巧
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int debug_num=0;
#define debug cout<<"debug "<<++debug_num<<" :"
const int maxn=200;
struct node{
string s;
ll v;
}no[maxn];
bool cmp(node a,node b)
{
if(a.v==b.v) return a.s<b.s;
return a.v>b.v;
}
int main()
{
//freopen("in.txt","r",stdin);
ios::sync_with_stdio(false);
int t;
cin>>t;
while(t--)
{
int n,m;
cin>>n>>m;
for(int i=0;i<n;++i){
cin>>no[i].s>>no[i].v;
}
sort(no,no+n,cmp);
// for(int i=0;i<n;++i){
// cout<<no[i].s<<" "<<no[i].v<<endl;
// }
ll sum=0;
ll tp=m;
for(int i=0;i<m;++i){
//cout<<no[i].s<<" ";
sum+=tp*no[i].v;
tp--;
}
cout<<sum<<" ";
for(int i=0;i<m;++i){
if(i==m-1) cout<<no[i].s<<endl;
else cout<<no[i].s<<" ";
}
}
return 0;
}
M
水题
无技巧
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int debug_num=0;
#define debug cout<<"debug "<<++debug_num<<" :"
int main()
{
//freopen("in.txt","r",stdin);
ios::sync_with_stdio(false);
int t;
cin>>t;
while(t--)
{
int n,b;
cin>>n>>b;
int flag=0;
for(int i=0;i<n;++i){
int tp;
cin>>tp;
if((tp+b)%7==0){
flag=1;
}
}
if(flag){
cout<<"Yes"<<endl;
}
else cout<<"No"<<endl;
}
return 0;
}