题目来源:https://ac.nowcoder.com/acm/contest/3003#question
这场就比较菜了,差点拿了一血,但是…就差一点点 点点点 实力是六题,因为有一题数据弱了… 先写着几个水题的题解,之后再补(可能明天)
UPD:补完了~
A - 做游戏
看代码都能懂
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<stack>
#include<queue>
#include<vector>
#include<set>
#include<map>
#include<string>
#define ls k<<1,l,mid
#define rs k<<1|1,mid+1,r
#define mp(x,y) make_pair(x,y)
#define r(x) read(x)
#define rrr(x,y,z) read(x);read(y);read(z)
#define FOR(i,l,r) for(int i=l;i<=r;i++)
using namespace std;
typedef long long LL;
typedef pair<int,int> pt;
const int N=1e6+5;
const int M=2e3+5;
const int INF=0x7fffffff;
const int mod=1e9+7;
const double eps=1e-8;
const double pi=acos(-1);
LL n,m;
template<class T>
inline void read(T &x)
{
char c; x=1;
while((c=getchar())<'0'||c>'9') if(c=='-') x=-1;
T res=c-'0';
while((c=getchar())>='0'&&c<='9') res=res*10+c-'0';
x*=res;
}
int main()
{
LL a,b,c,x,y,z;
rrr(a,b,c); rrr(x,y,z);
cout<<min(x,c)+min(y,a)+min(z,b)<<endl;
return 0;
}
B - 排数字
统计6 和 1出现的次数 ,设分别为a b ,那么答案就是max(min(a-1,b),0)
因为最简排法是 616161616 这样子
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<stack>
#include<queue>
#include<vector>
#include<set>
#include<map>
#include<string>
#define ls k<<1,l,mid
#define rs k<<1|1,mid+1,r
#define mp(x,y) make_pair(x,y)
#define r(x) read(x)
#define rrr(x,y,z) read(x);read(y);read(z)
#define FOR(i,l,r) for(int i=l;i<=r;i++)
using namespace std;
typedef long long LL;
typedef pair<int,int> pt;
const int N=1e6+5;
const int M=2e3+5;
const int INF=0x7fffffff;
const int mod=1e9+7;
const double eps=1e-8;
const double pi=acos(-1);
LL n,m;
char s[N];
template<class T>
inline void read(T &x)
{
char c; x=1;
while((c=getchar())<'0'||c>'9') if(c=='-') x=-1;
T res=c-'0';
while((c=getchar())>='0'&&c<='9') res=res*10+c-'0';
x*=res;
}
int main()
{
r(n);
int cnt1=0,cnt6=0;
scanf("%s",s+1);
FOR(i,1,n){
if(s[i]=='1') cnt1++;
else if(s[i]=='6') cnt6++;
}
cout<<max(0,min(cnt6-1,cnt1))<<endl;
return 0;
}
C - 算概率
设dp[ i ][ j ]为前i道题做出来j道的概率,可以在复杂度O(n2)内解决
转移方程为:dp[i][j]=(dp[i-1][j]*(1-f[i])+dp[i-1][j-1]*f[i]);
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<stack>
#include<queue>
#include<vector>
#include<set>
#include<map>
#include<string>
#define ls k<<1,l,mid
#define rs k<<1|1,mid+1,r
#define mp(x,y) make_pair(x,y)
#define r(x) read(x)
#define rrr(x,y,z) read(x);read(y);read(z)
#define FOR(i,l,r) for(int i=l;i<=r;i++)
using namespace std;
typedef long long LL;
typedef pair<int,int> pt;
const int N=1e6+5;
const int M=2e3+5;
const int INF=0x7fffffff;
const int mod=1e9+7;
const double eps=1e-8;
const double pi=acos(-1);
LL n,m;
LL dp[M][M];
LL f[N];
template<class T>
inline void read(T &x)
{
char c; x=1;
while((c=getchar())<'0'||c>'9') if(c=='-') x=-1;
T res=c-'0';
while((c=getchar())>='0'&&c<='9') res=res*10+c-'0';
x*=res;
}
int main()
{
r(n);
FOR(i,1,n){r(f[i]);}
dp[0][0]=1;
FOR(i,1,n){
dp[i][0]=dp[i-1][0]*(1-f[i]+mod)%mod;
FOR(j,1,i){
dp[i][j]=(dp[i-1][j]*(1-f[i]+mod)%mod+dp[i-1][j-1]*f[i]%mod)%mod;
}
}
FOR(i,0,n) cout<<dp[n][i]<<' ';
cout<<endl;
return 0;
}
D - 数三角
暴力,枚举三角形的三个点 a b c 通过向量乘积的正负判断是否有钝角 即可
但是要注意 三点一线的特判 if(xx*yyy==yy*xxx) return 0;
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<stack>
#include<queue>
#include<vector>
#include<set>
#include<map>
#include<string>
#define ls k<<1,l,mid
#define rs k<<1|1,mid+1,r
#define mp(x,y) make_pair(x,y)
#define r(x) read(x)
#define rrr(x,y,z) read(x);read(y);read(z)
#define FOR(i,l,r) for(int i=l;i<=r;i++)
using namespace std;
typedef long long LL;
typedef pair<int,int> pt;
const int N=1e6+5;
const int M=2e3+5;
const int INF=0x7fffffff;
const int mod=1e9+7;
const double eps=1e-8;
const double pi=acos(-1);
LL n,m;
struct point
{
int x,y;
}f[N];
template<class T>
inline void read(T &x)
{
char c; x=1;
while((c=getchar())<'0'||c>'9') if(c=='-') x=-1;
T res=c-'0';
while((c=getchar())>='0'&&c<='9') res=res*10+c-'0';
x*=res;
}
bool hhh(point a,point b,point c)
{
int xx=b.x-a.x,yy=b.y-a.y;
int xxx=c.x-a.x,yyy=c.y-a.y;
if(xx*yyy==yy*xxx) return 0;
return (xx*xxx+yy*yyy)<0;
}
int main()
{
r(n);
FOR(i,1,n){
scanf("%d%d",&f[i].x,&f[i].y);
}
int ans=0;
FOR(i,1,n){
FOR(j,i+1,n){
FOR(k,j+1,n){
point a=f[i];
point b=f[j];
point c=f[k];
if(hhh(a,b,c)||hhh(b,c,a)||hhh(c,b,a)){
ans++;
}
}
}
}
cout<<ans<<endl;
return 0;
}
E - 做计数
这题也算暴力吧。 首先两边平方 得到 i + j + sqrt(ij) = k
我们知道 i j k 都是整数 ,如果ij不能开方出整数 那肯定不行
所以枚举n以内所有的平方数 1 4 9 …
然后再统计这个平方数的因子即可
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<stack>
#include<queue>
#include<vector>
#include<set>
#include<map>
#include<string>
#define ls k<<1,l,mid
#define rs k<<1|1,mid+1,r
#define mp(x,y) make_pair(x,y)
#define r(x) read(x)
#define rrr(x,y,z) read(x);read(y);read(z)
#define FOR(i,l,r) for(int i=l;i<=r;i++)
using namespace std;
typedef long long LL;
typedef pair<int,int> pt;
const int N=1e6+5;
const int M=2e3+5;
const int INF=0x7fffffff;
const int mod=1e9+7;
const double eps=1e-8;
const double pi=acos(-1);
LL n,m;
template<class T>
inline void read(T &x)
{
char c; x=1;
while((c=getchar())<'0'||c>'9') if(c=='-') x=-1;
T res=c-'0';
while((c=getchar())>='0'&&c<='9') res=res*10+c-'0';
x*=res;
}
int main()
{
r(n);
LL ans=0;
FOR(i,1,n){
int t=sqrt(i);
if(t*t==i){
FOR(j,1,t){
if(i%j==0){
if(j==t) ans++;
else ans+=2;
}
}
}
}
cout<<ans<<endl;
return 0;
}
F - 拿物品
拿的物品a多或者b多对自己都是有好处的,效果相同。
我们以a+b的大小从大到小排序 正着取即可
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<stack>
#include<queue>
#include<vector>
#include<set>
#include<map>
#include<string>
#define ls k<<1,l,mid
#define rs k<<1|1,mid+1,r
#define mp(x,y) make_pair(x,y)
#define r(x) read(x)
#define rrr(x,y,z) read(x);read(y);read(z)
#define FOR(i,l,r) for(int i=l;i<=r;i++)
using namespace std;
typedef long long LL;
typedef pair<int,int> pt;
const int N=1e6+5;
const int M=2e3+5;
const int INF=0x7fffffff;
const int mod=1e9+7;
const double eps=1e-8;
const double pi=acos(-1);
LL n,m;
struct node
{
int a,b,id;
}f[N];
bool cmp(node a,node b)
{
return a.a+a.b>b.a+b.b;
}
template<class T>
inline void read(T &x)
{
char c; x=1;
while((c=getchar())<'0'||c>'9') if(c=='-') x=-1;
T res=c-'0';
while((c=getchar())>='0'&&c<='9') res=res*10+c-'0';
x*=res;
}
int main()
{
r(n);
FOR(i,1,n){
r(f[i].a);
f[i].id=i;
}
FOR(i,1,n) r(f[i].b);
sort(f+1,f+n+1,cmp);
for(int i=1;i<=n;i+=2) cout<<f[i].id<<' ';
cout<<endl;
for(int i=2;i<=n;i+=2) cout<<f[i].id<<' ';
cout<<endl;
return 0;
}
G - 判正误
这题数据太水,就是 hash ,看后面数据怎么加强 我的代码是错的
你们可以多取几个模 增加正确率
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<stack>
#include<queue>
#include<vector>
#include<set>
#include<map>
#include<string>
#define ls k<<1,l,mid
#define rs k<<1|1,mid+1,r
#define mp(x,y) make_pair(x,y)
#define r(x) read(x)
#define rrr(x,y,z) read(x);read(y);read(z)
#define FOR(i,l,r) for(int i=l;i<=r;i++)
using namespace std;
typedef long long LL;
typedef pair<int,int> pt;
const int N=1e6+5;
const int M=2e3+5;
const int INF=0x7fffffff;
const int mod=1e9+7;
const double eps=1e-8;
const double pi=acos(-1);
LL n,m;
struct node
{
int a,b,id;
}f[N];
bool cmp(node a,node b)
{
return a.a+a.b>b.a+b.b;
}
template<class T>
inline void read(T &x)
{
char c; x=1;
while((c=getchar())<'0'||c>'9') if(c=='-') x=-1;
T res=c-'0';
while((c=getchar())>='0'&&c<='9') res=res*10+c-'0';
x*=res;
}
LL qpow(LL a,LL p)
{
LL res=1;
while(p){
if(p&1) res=res*a%mod;
a=a*a%mod;
p>>=1;
}
return res;
}
int main()
{
int t;r(t);
while(t--){
LL a,b,c,d,e,f,g;
rrr(a,c,e); rrr(b,d,f); r(g);
if(qpow(a,b)+qpow(c,d)+qpow(e,f)==g) cout<<"Yes\n";
else cout<<"No\n";
}
return 0;
}
H - 施魔法
居然真是DP,dp[ i ]表示的是 取前i个所消耗的最少魔力
转移方程为:dp[i]=min(dp[i-1]+f[i]-f[i-1],dp[i-m]+f[i]-f[i-m+1]);
可以这样想,假如现在已经分了k段了,你要么把下一个加入第k段,要么让这最后k个另成一段,取最小值.
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<stack>
#include<string>
#include<queue>
#include<vector>
#include<set>
#include<map>
#define ls k<<1,l,mid
#define rs k<<1|1,mid+1,r
#define FOR(i,l,r) for(int i=l;i<=r;i++)
#define mp(x,y) make_pair(x,y)
#define pb(x) push_back(x)
#define r(x) read(x)
#define rrr(x,y,z) read(x);read(y);read(z)
using namespace std;
const int N=1e6+5;
const int M=2e3+5;
const int sz=17;
const int INF=0x7fffffff;
const int mod=1e9+7;
const double eps=1e-8;
const double pi=acos(-1);
typedef long long LL;
typedef pair<int,int> pt;
LL n,m;
int f[N];
int dp[N];
template<class T>
inline void read(T &x)
{
char c; x=1;
while((c=getchar())<'0'||c>'9') if(c=='-') x=-1;
T res=c-'0';
while((c=getchar())>='0'&&c<='9') res=res*10+c-'0';
x*=res;
}
int main()
{
r(n); r(m);
FOR(i,1,n) r(f[i]);
sort(f+1,f+n+1);
FOR(i,1,n) dp[i]=f[i]-f[1];
FOR(i,2*m,n){
dp[i]=min(dp[i-1]+f[i]-f[i-1],dp[i-m]+f[i]-f[i-m+1]);
}
cout<<dp[n]<<endl;
return 0;
}
I - 建通道
我的写法复杂了,因为一开始题目看错了 写成这丑样了,然后懒得改太多…
如果有相同的元素 那肯定让他们之间连通 因为花费为0 把相同的去重掉就好了。 然后我们肯定是希望lowbit越小越好,我们就从最低为开始往高位枚举,设目前到了第k+1位 那如果这个元素&(1<<k) =1 把他放入一个集合A =0 放入一个集合 B 如果这两个集合都不为空 ,我们让这两个集合的元素互相连通就是让所以元素连通了。 比如 A中有 a1 a2 ,B中有b1 b2 ,我们让a1 连 b1 b2 ,a2连b1即可,一共花费即为 (1<<k)*(n-1)
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<stack>
#include<queue>
#include<vector>
#include<set>
#include<map>
#include<string>
#define ls k<<1,l,mid
#define rs k<<1|1,mid+1,r
#define mp(x,y) make_pair(x,y)
#define r(x) read(x)
#define rrr(x,y,z) read(x);read(y);read(z)
#define FOR(i,l,r) for(int i=l;i<=r;i++)
using namespace std;
typedef long long LL;
typedef pair<int,int> pt;
const int N=1e6+5;
const int M=2e3+5;
const int INF=0x7fffffff;
const int mod=1e9+7;
const double eps=1e-8;
const double pi=acos(-1);
LL n,m;
int f[N];
LL ans;
template<class T>
inline void read(T &x)
{
char c; x=1;
while((c=getchar())<'0'||c>'9') if(c=='-') x=-1;
T res=c-'0';
while((c=getchar())>='0'&&c<='9') res=res*10+c-'0';
x*=res;
}
void hhh(vector<int> v,LL st)
{
vector<int> v1,v2;
bool f1=0,f2=0;
FOR(i,0,v.size()-1){
if(v[i]&st){
f1=1;
v1.push_back(v[i]);
}
else{
f2=1;
v2.push_back(v[i]);
}
}
if(f1&&f2){
LL res=st*(v1.size()+v2.size()-1);
ans=min(ans,res);
return ;
}
if(f1) hhh(v1,st<<1);
if(f2) hhh(v2,st<<1);
}
int main()
{
r(n);
FOR(i,1,n){
r(f[i]);
}
sort(f+1,f+n+1);
n=unique(f+1,f+n+1)-f-1;
ans=0;
if(n==0||n==1) cout<<ans<<endl;
else{
ans=INF;
vector<int> v;
FOR(i,1,n) v.push_back(f[i]);
hhh(v,1);
cout<<ans<<endl;
}
return 0;
}
J - 求函数
这题看出来了是线段树 但是自己不知道改维护什么
那就维护k的乘积和那个和就完事~
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<stack>
#include<string>
#include<queue>
#include<vector>
#include<set>
#include<map>
#define ls k<<1,l,mid
#define rs k<<1|1,mid+1,r
#define FOR(i,l,r) for(int i=l;i<=r;i++)
#define mp(x,y) make_pair(x,y)
#define pb(x) push_back(x)
#define r(x) read(x)
#define rrr(x,y,z) read(x);read(y);read(z)
using namespace std;
const int N=1e6+5;
const int M=2e3+5;
const int sz=17;
const int INF=0x7fffffff;
const int mod=1e9+7;
const double eps=1e-8;
const double pi=acos(-1);
typedef long long LL;
typedef pair<LL,LL> pt;
LL n,m;
int kkk[N],ans1[N],ans2[N];
template<class T>
inline void read(T &x)
{
char c; x=1;
while((c=getchar())<'0'||c>'9') if(c=='-') x=-1;
T res=c-'0';
while((c=getchar())>='0'&&c<='9') res=res*10+c-'0';
x*=res;
}
void update(int k,int l,int r,int pos,int kk,int b)
{
if(l==r){
ans1[k]=kk;
ans2[k]=b;
return ;
}
int mid=(l+r)>>1;
if(mid>=pos) update(ls,pos,kk,b);
else update(rs,pos,kk,b);
ans1[k]=1ll*ans1[k<<1]*ans1[k<<1|1]%mod;
ans2[k]=(1ll*ans2[k<<1]*ans1[k<<1|1]+ans2[k<<1|1])%mod;
}
pt merge_pt(pt p1,pt p2)
{
return mp(1ll*p1.first*p2.first%mod,(1ll*p1.second*p2.first%mod+p2.second)%mod);
}
pt query(int k,int l,int r,int x,int y)
{
if(x<=l&&r<=y){
return mp(ans1[k],ans2[k]);
}
int mid=(l+r)>>1;
pt pp=mp(1,0);
if(mid>=x) pp=merge_pt(pp,query(ls,x,y));
if(mid<y) pp=merge_pt(pp,query(rs,x,y));
return pp;
}
int main()
{
r(n); r(m);
FOR(i,1,n) r(kkk[i]);
FOR(i,1,n){
LL b;r(b);
update(1,1,n,i,kkk[i],b);
}
while(m--){
int op;
r(op);
if(op==1){
int i,k,b;
rrr(i,k,b);
update(1,1,n,i,k,b);
}
else{
int l,r;
r(l); r(r);
pt pp=query(1,1,n,l,r);
//cout<<pp.first<<' '<<pp.second<<endl;
cout<<(pp.first+pp.second)%mod<<endl;
}
}
return 0;
}
下次加油哇~争取多A个题