今天真爆炸。。
T2 忘打回车 爆9
T3 复制时没把visb改成visa 52->9
本来100+100+52+27+0+43=322 结果炸成186。。
这几天总是出各种低级失误,从没加分号到二进制拆分写错,忘打回车……总共也算丢了几百分吧,很致命!
以后要重视细节检查,争取发挥出应有水平!
更新题解:
T1
Description:
定义一个 6 位数是 lucky 的,当且仅当它的前 3 位之和等于后 3 位之和,比如 165912 给出数 x,找出最小的、大于 x 的幸运数字。 无解输出-1
题解:
直接模拟即可(这道题居然不会有-1。。)
std
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<ctime>
#include<vector>
#include<queue>
#include<algorithm>
#include<string>
#include<sstream>
#include<cctype>
#include<cmath>
#include<iomanip>
#include<map>
#include<stack>
#include<set>
#include<functional>
#define in(x) x=read()
#define qr read()
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
inline int read()
{
char ch=' ';
int f=1,x=0;
while(!isdigit(ch)){ch=getchar();if(ch=='-')f*=-1;}
while(isdigit(ch)){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
return f*x;
}
inline bool check(int x){return (x%10+x/10%10+x/100%10)==(x/100000+x/10000%10+x/1000%10);}
int main()
{
freopen("lucky.in","r",stdin);
freopen("lucky.out","w",stdout);
int x;
in(x);x++;
while(!check(x))
{
x++;
if(x>=1000000)
{
cout<<-1;
return 0;
}
}
cout<<x;
return 0;
}
T2
Description:
街道上有 n 个点 x1,x2,…,xn。你可以在其中一个点开始行程,在任何一个点结束。要求遍历所有点。从点 i 走到点 j,需要花费 abs(xi – xj)的时间。请问最少花费多少时间。
题解:
观察可知答案为max-min(计算时间时不会考虑中间的点)
然而我处理多组数据时没输回车。。爆9
std:
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<ctime>
#include<vector>
#include<queue>
#include<algorithm>
#include<string>
#include<sstream>
#include<cctype>
#include<cmath>
#include<iomanip>
#include<map>
#include<stack>
#include<set>
#include<functional>
#define in(x) x=read()
#define qr read()
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
inline int read()
{
char ch=' ';
int f=1,x=0;
while(!isdigit(ch)){ch=getchar();if(ch=='-')f*=-1;}
while(isdigit(ch)){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
return f*x;
}
int main()
{
freopen("salesman.in","r",stdin);
freopen("salesman.out","w",stdout);
int t;in(t);
int y;
while(t--)
{
int n;in(n);
int minn=1010,maxx=-1;
for(int i=1;i<=n;i++)in(y),minn=min(minn,y),maxx=max(maxx,y);
cout<<maxx-minn<<endl;
}
return 0;
}
T3
Description:
有两个数组 A,B,大小均为 N。请在 A 中选择一个数 x,B 中选择一个数 y,使得 gcd(x,y) 最大;如果有多组数 gcd 相同,找出 x+y 最大的。
题解:
处理A,B数组的所有约数与此约数的最大原数,枚举即可
处理约数方法:
(1)考试时方法:$O(n*\sqrt{n})$,暴力枚举每个数的所有因数
然而考试时复制后忘把visa改成visb。。
而且这种方法只能得52分(最慢的点2.5秒)
(2)AC代码:枚举因子与倍数,判断倍数是否存在(O($n*\log n$))
$O(n*\sqrt{n})$ TLE代码:
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<ctime>
#include<vector>
#include<queue>
#include<algorithm>
#include<string>
#include<sstream>
#include<cctype>
#include<cmath>
#include<iomanip>
#include<map>
#include<stack>
#include<set>
#include<functional>
#define in(x) x=read()
#define qr read()
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
inline int read()
{
char ch=' ';
int f=1,x=0;
while(!isdigit(ch)){ch=getchar();if(ch=='-')f*=-1;}
while(isdigit(ch)){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
return f*x;
}
int a[5000010],b[5000010],pp1[5000010]={0},pp2[5000010]={0};
int vis1[5000010]={0},vis2[5000010]={0},nn1[5000010]={0},nn2[5000010]={0};
int main()
{
freopen("gcd.in","r",stdin);
freopen("gcd.out","w",stdout);
int n;
in(n);
for(int i=1;i<=n;i++)in(a[i]);
for(int i=1;i<=n;i++)in(b[i]);
pp1[1]=pp2[1]=1;
for(register int i=1;i<=n;i++)
{
int t=sqrt(a[i]);
for(register int j=1;j<=t;j++)
{
if(a[i]%j==0)pp1[j]=pp1[a[i]/j]=1,nn1[j]=max(nn1[j],a[i]),nn1[a[i]/j]=max(nn1[a[i]/j],a[i]);
}
}
for(register int i=1;i<=n;i++)
{
int t=sqrt(b[i]);
for(register int j=1;j<=t;j++)
{
if(b[i]%j==0)pp2[j]=pp2[b[i]/j]=1,nn2[j]=max(nn2[j],b[i]),nn2[b[i]/j]=max(nn2[b[i]/j],b[i]);
}
}
int ans;
for(int i=1000000;i>=1;i--)
{
if(pp1[i]&&pp2[i])
{
cout<<nn1[i]+nn2[i];
return 0;
}
}
return 0;
}
std:
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<ctime>
#include<vector>
#include<queue>
#include<algorithm>
#include<string>
#include<sstream>
#include<cctype>
#include<cmath>
#include<iomanip>
#include<map>
#include<stack>
#include<set>
#include<functional>
#define in(x) x=read()
#define qr read()
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
inline int read()
{
char ch=' ';
int f=1,x=0;
while(!isdigit(ch)){ch=getchar();if(ch=='-')f*=-1;}
while(isdigit(ch)){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
return f*x;
}
int a[5000010],b[5000010],pp1[5000010]={0},pp2[5000010]={0},t[1000010]={0};
int vis1[5000010]={0},vis2[5000010]={0},nn1[5000010]={0},nn2[5000010]={0};
int main()
{
freopen("gcd.in","r",stdin);
freopen("gcd.out","w",stdout);
int n;
in(n);
for(int i=1;i<=n;i++)in(a[i]),t[a[i]]++;
for(int i=1;i<=n;i++)in(b[i]);
for(int i=1;i<=1000000;i++)
{
for(int j=i;j<=1000000;j+=i)
{
if(t[j])
{
pp1[i]=1;
nn1[i]=max(nn1[i],j);
}
}
}
for(int i=1;i<=n;i++)t[a[i]]--,t[b[i]]++;
for(int i=1;i<=1000000;i++)
{
for(int j=i;j<=1000000;j+=i)
{
if(t[j])
{
pp2[i]=1;
nn2[i]=max(nn2[i],j);
}
}
}
for(int i=1000000;i>=1;i--)
{
if(pp1[i]&&pp2[i])
{
cout<<nn1[i]+nn2[i];
return 0;
}
}
return 0;
}
T4
Description:
蓝月商场有 n 件宝贝,每件宝贝有两个属性:价钱 price 和品牌 brand。其中 brand 是 1-5 之间某个整数。每件宝贝价钱两两不同。 贪玩蓝月有 Q 个代言人,每个代言人拍完戏之后,希望能从蓝月商场免费顺走一样宝贝。但是每个代言人有自己的喜好,例如古天乐只喜欢品牌 1,陈小春喜欢品牌 1 或品牌 2,渣渣辉喜欢品牌 3 和 5……具体来说,代言人会有 d 个喜欢的品牌(1 <= d <= 5),同时他最喜欢这些品牌中,价钱第 k 便宜的宝贝。
题解:
(考试时直接打了暴力)
预处理b[i][j]表示价格前i的物品中第j品牌有多少,询问时二分位置
std:
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<ctime>
#include<vector>
#include<queue>
#include<algorithm>
#include<string>
#include<sstream>
#include<cctype>
#include<cmath>
#include<iomanip>
#include<map>
#include<stack>
#include<set>
#include<functional>
#define in(x) x=read()
#define qr read()
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
inline int read()
{
char ch=' ';
int f=1,x=0;
while(!isdigit(ch)){ch=getchar();if(ch=='-')f*=-1;}
while(isdigit(ch)){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
return f*x;
}
struct ee
{
int t;
int p;
}a[500010];
bool cmp(ee a1,ee a2)
{
return a1.p<a2.p;
}
int p[500010],e[500010],b[500010][6]={0},now=0,d;
int check(int x)
{
int ans=0;
for(int i=1;i<=d;i++)
{
// printf("b[%d][%d]=%d\n",x,e[i],b[x][e[i]]);
ans+=b[x][e[i]];
}
return ans;
}
int main()
{
freopen("purchase.in","r",stdin);
freopen("purchase.out","w",stdout);
int n;in(n);
for(int i=1;i<=n;i++)in(a[i].t);
for(int i=1;i<=n;i++)in(a[i].p);
sort(a+1,a+1+n,cmp);
for(int i=1;i<=n;i++)
{
for(int j=1;j<=5;j++)b[i][j]=b[i-1][j];
b[i][a[i].t]++;
}
int q;in(q);
while(q--)
{
in(d);
for(int i=1;i<=d;i++)in(e[i]);
int k;in(k);
if(check(n)<k)
{
cout<<-1<<endl;
}
else
{
int l=1,r=n;
while(l<r)
{
int mid=(l+r)>>1;
if(check(mid)>=k)r=mid;
else l=mid+1;
}
cout<<a[l].p<<endl;
}
}
return 0;
}
T5
Description:
有两个仅包含小写字母的字符串 x,y, 长度分别为 n,m。 你需要修改 x 串中某些字符, 是的新的 x 串和 y 串的最长公共子序列长度至少为 k。 我们将’a’…’z’对应成 0…25, 修改两个字符付出的代价,为它们对应的数的 xor 值。 比如 说,将’a’修改成’z’代价为 0 xor 25=25。 请问最少付出多少代价,使得新的 x 串和 y 串的 LCS 大于等于 k。
题解:
“非常基础”的dp?
定义f[i][j][k]表示使x前i字符,y前j字符的LCS等于k需付出代价
边界:
k=0:为0
i=0,j!=0或j=0,i!=0:为inf
转移:
$f[i][j][k]=min(f[i][j-1][k],min(f[i-1][j][k],f[i-1][j-1][k-1]+a[i][j]))$(a:代价)
std:
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<ctime>
#include<vector>
#include<queue>
#include<algorithm>
#include<string>
#include<sstream>
#include<cctype>
#include<cmath>
#include<iomanip>
#include<map>
#include<stack>
#include<set>
#include<functional>
#define in(x) x=read()
#define qr read()
#define inf 2000000000
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
inline int read()
{
char ch=' ';
int f=1,x=0;
while(!isdigit(ch)){ch=getchar();if(ch=='-')f*=-1;}
while(isdigit(ch)){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
return f*x;
}
string s1,s2;
int dp[400][400][400]={0};
int a[30][30]={0};
int work(int n,int m,int k)
{
if(!k)return 0;
if(m<k||n<k)return inf;
if(dp[n][m][k]!=-1)return dp[n][m][k];
dp[n][m][k]=min(work(n-1,m,k),min(work(n,m-1,k),work(n-1,m-1,k-1)+a[s1[n-1]-'a'][s2[m-1]-'a']));
return dp[n][m][k];
}
int main()
{
freopen("string.in","r",stdin);
freopen("string.out","w",stdout);
int n=qr,m=qr,k=qr;
memset(dp,-1,sizeof(dp));
cin>>s1>>s2;
for(int i=0;i<=25;i++)
{
for(int j=0;j<=25;j++)
{
a[i][j]=i^j;
}
}
int ans=work(n,m,k);
if(ans>=2000000000)cout<<-1;
else cout<<ans;
return 0;
}
T6
Description:
给出长度为 n 的序列 A1,A2,…,An。进行 m 次操作,有三种类型: 1、 给出 l,r,将区间[l,r]的 Ai 都加一。 2、 给出 l,r,询问区间[l,r]的 Ai!的和,对 10^9 取模。 3、 给出 I,v,将 Ai 单点修改为 v。
题解:
(考试时依然打了暴力)
用线段树维护最小值与阶乘,支持单点修改,区间求和
区间修改:发现当x>=40时,
$x! mod 10^9=0$!!
通过最小值找到所有小于40的数后单点修改
每个数最多被修改40次,所以总复杂度为$O((n+q)*50*log n)$
std:
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<ctime>
#include<vector>
#include<queue>
#include<algorithm>
#include<string>
#include<sstream>
#include<cctype>
#include<cmath>
#include<iomanip>
#include<map>
#include<stack>
#include<set>
#include<functional>
#define mod 1000000000
#define in(x) x=read()
#define qr read()
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
inline int read()
{
char ch=' ';
int f=1,x=0;
while(!isdigit(ch)){ch=getchar();if(ch=='-')f*=-1;}
while(isdigit(ch)){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
return f*x;
}
ll a[2000010],c[2000010],f[2000010];
int n;
ll fac[50]={0,1,2,6,24,120,720,5040,40320,362880,3628800,39916800,479001600,227020800,178291200,674368000,789888000,428096000,705728000,408832000,176640000,709440000,607680000,976640000,439360000,984000000,584000000,768000000,504000000,616000000,480000000,880000000,160000000,280000000,520000000,200000000,200000000,400000000,200000000,800000000};
void pushup(int x)
{
c[x]=min(c[x<<1],c[x<<1|1]);
f[x]=f[x<<1]+f[x<<1|1]%mod;
}
void build(int l,int r,int x)
{
if(l==r)
{
c[x]=a[l];
if(a[l]>=40)f[x]=0;
else f[x]=fac[a[l]];
return;
}
int mid=(l+r)>>1;
build(l,mid,x<<1);
build(mid+1,r,x<<1|1);
pushup(x);
}
void update1(int pl,int pr,int cc,int v,int x)
{
if(pl==pr)
{
c[x]=v;
if(v>=40)f[x]=0;
else f[x]=fac[v];
return;
}
int mid=(pl+pr)>>1;
if(mid>=cc)update1(pl,mid,cc,v,x<<1);
else update1(mid+1,pr,cc,v,x<<1|1);
pushup(x);
}
//int query1(int l,int r,int v,int x)
//{
// if(l==r)return c[x];
// int mid=(l+r)>>1;
// if(mid>=v)return query1(l,mid,v,x<<1);
// else return query1(mid+1,r,v,x<<1|1);
//}
void update2(int l,int r,int pl,int pr,int x)
{
if(pl==pr)
{
// update1(l,r,l,c[x]+1,x);
c[x]++;
if(c[x]>=40)f[x]=0;
else f[x]=fac[c[x]];
return;
}
int mid=(pl+pr)>>1;
if(c[x<<1]<40&&l<=mid)
{
update2(l,r,pl,mid,x<<1);
}
if(c[x<<1|1]<40&&mid<r)
{
update2(l,r,mid+1,pr,x<<1|1);
}
pushup(x);
}
ll query2(int l,int r,int pl,int pr,int x)
{
if(l<=pl&&pr<=r)return f[x]%mod;
int mid=(pl+pr)>>1;
ll ans=0;
if(l<=mid)ans+=query2(l,r,pl,mid,x<<1);
if(mid<r)ans+=query2(l,r,mid+1,pr,x<<1|1);
return ans%mod;
}
int main()
{
freopen("array.in","r",stdin);
freopen("array.out","w",stdout);
int m;
in(n),in(m);
for(int i=1;i<=n;i++)in(a[i]);
build(1,n,1);
for(int i=1;i<=m;i++)
{
int op;
in(op);
if(op==1)
{
int l,r;
in(l),in(r);
update2(l,r,1,n,1);
}
else if(op==2)
{
int l,r;
in(l),in(r);
cout<<query2(l,r,1,n,1)<<endl;
}
else
{
int l,v;
in(l),in(v);
update1(1,n,l,v,1);
}
}
return 0;
}