题目来源:https://ac.nowcoder.com/acm/contest/3005#question
这场居然没人AK,难度真的不小啊(后两题都没看)
第一题跟着递归式子反递推就好了,假如我们现在某一步是 x y 那下一步递归是 a b
那么a=y , b=x%y 即可得 上一步是 ak+b , b 取k=1时最小
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#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=2e5+5;
const int M=2e3+5;
const int INF=0x7fffffff;
const int mod=998244353;
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()
{
int t;
r(t);
while(t--){
r(n);
LL a=1,b=0;
if(n>=1){
a=2; b=1;
n--;
}
FOR(i,1,n){
LL tmp=a;
a=a+b;
b=tmp;
}
cout<<a+b<<endl;
}
return 0;
}
类似括号匹配,丢到栈里面 有一对就出栈,最后看栈是否为空
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#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()
{
scanf("%s",s+1);
int len=strlen(s+1);
stack<char> ss;
FOR(i,1,len){
if(ss.size()){
char c=ss.top();
if(c=='('&&s[i]==')') ss.pop();
else if(c=='{'&&s[i]=='}') ss.pop();
else if(c=='['&&s[i]==']') ss.pop();
else ss.push(s[i]);
}
else ss.push(s[i]);
}
if(ss.size()) cout<<"No\n";
else cout<<"Yes\n";
return 0;
}
我又是线段树,其实可以不用,做个标记哪些值为0,哪些不会0就好了
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#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=2e5+5;
const int M=2e3+5;
const int INF=0x7fffffff;
const int mod=998244353;
const double eps=1e-8;
const double pi=acos(-1);
LL n,m;
LL f[N];
LL sum[N<<2];
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;
}
LL inv(LL x)
{
return qpow(x,mod-2);
}
void build(int k,int l,int r)
{
if(l==r){
sum[k]=f[l];
return ;
}
int mid=(l+r)>>1;
build(ls); build(rs);
sum[k]=sum[k<<1]*sum[k<<1|1]%mod;
}
LL query(int k,int l,int r,int x,int y)
{
if(x<=l&&r<=y){
return sum[k];
}
int mid=(l+r)>>1;
LL res=1;
if(mid>=x) res=res*query(ls,x,y)%mod;
if(mid<y) res=res*query(rs,x,y)%mod;
return res;
}
int main()
{
r(n); r(m);
LL now=1;
FOR(i,1,n){
r(f[i]);
}
build(1,1,n);
LL ans=0;
FOR(i,m,n){
ans=max(ans,query(1,1,n,i-m+1,i));
}
cout<<ans<<endl;
return 0;
}
假如第i为开头到第j为的连续子串异或为0,那么此时1到j的前缀异或就等于1到i-1的前缀异或,我们用map记录前缀异或即可
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#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=2e5+5;
const int M=2e3+5;
const int INF=0x7fffffff;
const int mod=998244353;
const double eps=1e-8;
const double pi=acos(-1);
LL n,m;
LL f[N];
LL sum[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);
map<LL,LL> mm;
FOR(i,1,n){
r(f[i]);
sum[i]=sum[i-1]^f[i];
mm[sum[i]]++;
}
LL now=0;
LL ans=0;
FOR(i,1,n){
//cout<
if(i>1) mm[sum[i-1]]--;
if(mm.count(sum[i-1])) ans+=mm[sum[i-1]];
//cout<
}
cout<<ans<<endl;
return 0;
}
有种高精度加法的感觉,但是我们可以优化,每次只加一个位的某个数
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#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=998244353;
const double eps=1e-8;
const double pi=acos(-1);
LL n,m;
char str[N];
char num[N];
int ans[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 add(int x,int pos)
{
// cout<
int sum=ans[pos]+x;
// cout<
if(sum>=10){
ans[pos]=sum%10;
int i=pos+1;
// cout<
while(ans[i]+1>=10){
ans[i]=0;
i++;
}
ans[i]++;
}
else ans[pos]=sum;
// for(int i=pos+4;i>=1;i--) cout<
// cout<
}
bool cmp(char a,char b)
{
return a>b;
}
int main()
{
scanf("%s",str+1);
int len=strlen(str+1);
int add_num=0;
int cnt=0;
FOR(i,1,len){
if(str[i]=='+') add_num++;
else num[++cnt]=str[i];
}
int sep=add_num+1;
memset(ans,0,sizeof ans);
sort(num+1,num+cnt+1,cmp);
int now=0,pos=1;
FOR(i,1,cnt){
now++;
add(num[i]-'0',pos);
if(now==sep){
now=0;
pos++;
}
}
int get=-1;
for(int i=5e5+100;i>=1;i--)
if(ans[i]!=0){
get=i;
break;
}
//cout<
for(int i=get;i>=1;i--) printf("%d",ans[i]);
cout<<endl;
return 0;
}
不难发现,只有两人相距偶数条边时,必胜,遍历一遍图,找到所有点到根的距离 记录奇偶点个数即可
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#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=998244353;
const double eps=1e-8;
const double pi=acos(-1);
LL n,m;
vector<int> v[N];
int num[N];
struct node
{
int v,step;
};
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 bfs(int x)
{
node p;
p.v=x; p.step=0;
queue<node> q;
q.push(p);
while(q.size()){
node now=q.front();
q.pop();
num[now.v]=now.step;
for(int i=0;i<v[now.v].size();i++){
node next;
next.v=v[now.v][i];
next.step=now.step+1;
q.push(next);
}
}
}
int main()
{
r(n);
FOR(i,1,n-1){
int a;r(a);
v[a].push_back(i+1);
}
num[1]=0;
bfs(1);
int cnt1=0,cnt2=0;
LL ans=0;
FOR(i,1,n){
if(num[i]&1) cnt1++;
else cnt2++;
}
ans+=1ll*cnt1*(cnt1-1);
ans+=1ll*cnt2*(cnt2-1);
cout<<ans<<endl;
return 0;
}
二分答案,对于每个mid,最多只有始终概率,通过n*p就可以算出期望
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#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=998244353;
const double eps=1e-8;
const double pi=acos(-1);
LL n,m;
int num[20];
double p[20];
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){
int a;
r(a);
num[a-90]++;
}
double l=0,r=1;
while(r-l>=eps){
double mid=(l+r)/2;
double res=0;
FOR(i,1,10){
p[i]=(90.0-(i+90)*(1-mid))/mid;
p[i]=1.0-p[i]/90;
if(p[i]>1) p[i]=1;
res+=p[i]*num[i];
}
//cout<<(res>=n/10)<
if(res>=n/10) l=mid+eps;
else r=mid-eps;
}
printf("%.2f%%\n",100*l);
return 0;
}
线段树写的,我看出题人那个思维我还是不习惯,自己想了一个写法。
先用g统计1到n颜色的总数量,然后gg统计1到i-1的颜色数量,每次都只改变一个点,我们只需要更新这个点的颜色贡献,贡献值为res=1ll*(g[f[i].c]-1-gg[f[i].c])*gg[f[i].c];
然后查询就好了。这题有点卡常,加了个ll rr就A了
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#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=5e5+5;
const int M=2e3+5;
const int INF=0x7fffffff;
const int mod=998244353;
const double eps=1e-8;
const double pi=acos(-1);
LL n,m;
struct in
{
int c,l,r;
}f[N];
LL g[N];
LL gg[N];
LL sum[N<<2];
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,LL v)
{
if(l==r){
sum[k]=v;
return ;
}
int mid=(l+r)>>1;
if(mid>=pos) update(ls,pos,v);
else update(rs,pos,v);
sum[k]=sum[k<<1]+sum[k<<1|1];
}
LL query(int k,int l,int r,int x,int y)
{
if(x<=l&&r<=y){
return sum[k];
}
int mid=(l+r)>>1;
LL res=0;
if(mid>=x) res+=query(ls,x,y);
if(mid<y) res+=query(rs,x,y);
return res;
}
int main()
{
r(n);
int ll=INF,rr=0;
FOR(i,1,n){
rrr(f[i].c,f[i].l,f[i].r);
g[f[i].c]++;
ll=min(f[i].c,ll);
rr=max(f[i].c,rr);
}
LL res;
FOR(i,1,n){
if(f[i].l<=f[i].c&&f[i].c<=f[i].r){
res=1ll*(g[f[i].c]-1-gg[f[i].c])*gg[f[i].c];
update(1,ll,rr,f[i].c,res);
}
cout<<query(1,ll,rr,f[i].l,f[i].r)<<' ';
gg[f[i].c]++;
res=1ll*(g[f[i].c]-gg[f[i].c])*gg[f[i].c];
update(1,ll,rr,f[i].c,res);
}
return 0;
}
这题是个贪心。
思路先对原来的按x的大小排序,从左到右遍历,碰到z=0的就将其加入multiset,碰到z=1的就判断集合里面有没有y小于它的,找到最大的那个y从集合中删去,这就匹配了一对,具体贪心证明请看
https://ac.nowcoder.com/discuss/365889?type=101&order=0&pos=9&page=3
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#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=998244353;
const double eps=1e-8;
const double pi=acos(-1);
LL n,m;
struct node
{
int x,y,z;
}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 cmp(node a,node b)
{
return a.x<b.x;
}
int main()
{
r(n);
FOR(i,1,n){
rrr(f[i].x,f[i].y,f[i].z);
}
sort(f+1,f+n+1,cmp);
multiset<int> s;
multiset<int>::iterator it;
int ans=0;
FOR(i,1,n){
if(f[i].z){
if(s.size()){
it=s.lower_bound(f[i].y);
if(it!=s.begin()){
it--;
s.erase(it);
ans++;
}
}
}
else s.insert(f[i].y);
}
cout<<ans<<endl;
return 0;
}