https://ac.nowcoder.com/acm/contest/3005#question
D
al…ar=sum[r]^sum[l-1]=0 1-r 1-l-1异或抵消前面相同的为l-r异或
mp[0]=1必须写
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=2e5+5;
ll n,a[maxn],sum[maxn],ans;
map<ll,ll> mp;//2^30=1e9 该异或前缀和最大出现2e5次
int main(){
cin>>n;
mp[0]++;//ai可以为0
for(int i=1;i<=n;i++){
cin>>a[i];
sum[i]=sum[i-1]^a[i];
if(mp.count(sum[i])){ //sum[r]^sum[l-1]=0 有多少sum[l-1]与sum[r]相同的数字就有多少种异或为0的情况
ans+=mp[sum[i]];
}
mp[sum[i]]++; //之前未出现过也++
}
cout<<ans<<endl;
return 0;
}
F
牛牛胜 main函数中要写dfs(1,1)
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e6+5;
ll n,a[maxn],fa,ans,cnt0,cnt1;
vector<ll> v[maxn]; //父亲在1-1e6内
//距离为偶数 先手胜 == 2个深度为奇数的点距离为偶数 2个深度为偶数的点距离为偶数
void dfs(ll x,ll dep){
if(dep&1) cnt1++;
else cnt0++;
for(int i=0;i<v[x].size();i++)
dfs(v[x][i],dep+1);
}
int main(){
cin>>n;
for(int i=2;i<=n;i++){
cin>>fa;
v[fa].push_back(i);
}
dfs(1,1);//根节点为1 深度为1
ans=cnt1*(cnt1-1)+cnt0*(cnt0-1);
cout<<ans<<endl;
return 0;
}
F 01染色
#include <algorithm>
#include <cmath>
#include <iostream>
#include <map>
#include <set>
#include <stack>
#include <vector>
const long long MOD = 1e9 + 7;
const int MAXN = 1e6 + 7;
std::vector<int> edge[MAXN];
std::vector<int> color(MAXN);
void dfs(int u, int c) {
for (auto &v : edge[u]) {
color[v] = c ^ 1;
dfs(v, c ^ 1);
}
}
int main() {
int n;
std::cin >> n;
for (int i = 2; i <= n; ++i) {
int x;
std::cin >> x;
edge[x].emplace_back(i);
}
color[1] = 0;
dfs(1, 0);//染成0 深度为奇数的点 下一层染成1 深度为偶数的点
long long x1 = 0, x2 = 0;
for (int i = 1; i <= n; ++i) {
if (color[i]) {
++x1;
} else {
++x2;
}
}
std::cout << x1 * (x1 - 1) + x2 * (x2 - 1) << "\n";
return 0;
}
B
栈为空扫到右括号 右括号多余
栈不空 左括号多余
栈顶左括号与当前扫到右括号不匹配 不弹栈 栈不空
不合法 右括号始终不进栈 左括号不出栈
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e5+5;
const int mod=1e9+7;
#define mp make_pair
#define fi first
#define se second
ll t,n,m,k,ans;
ll a[maxn],f;
string s;
stack<char> st;
int main(){
cin>>s;
ll len=s.size();
for(int i=0;i<len;i++){
if(s[i]=='{' || s[i]=='[' || s[i]=='(')
st.push(s[i]);
else if((s[i]==']' || s[i]=='}' || s[i]==')') && st.empty()){
f=1;
break;
}
else if(s[i]=='}' && st.top()=='{')
st.pop();
else if(s[i]==']' && st.top()=='[')
st.pop();
else if(s[i]==')' && st.top()=='(')
st.pop();
}
if(!st.empty())
f=1;
if(f)
cout<<"No"<<endl;
else
cout<<"Yes"<<endl;
return 0;
}
手写栈
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e6+5;
ll n,a[maxn],ans,now,len,f;
char st[maxn];
string s;
int main(){
f=1;
cin>>s;
len=s.size();
for(int i=0;i<len;i++){
if(s[i]=='[' || s[i]=='(' || s[i]=='{')
st[++now]=s[i];
else if(s[i]==']'){
if(st[now]=='[')
now--;
else{ //不匹配 或 栈空右括号多余
f=0;
break;
}
}
else if(s[i]==')'){
if(st[now]=='(')
now--;
else{
f=0;
break;
}
}
else if(s[i]=='}'){
if(st[now]=='{')
now--;
else{
f=0;
break;
}
}
}
if(f && now==0) //栈空右括号不多余 括号匹配
cout<<"Yes"<<endl;
else
cout<<"No"<<endl;
return 0;
}
C
取mod 998244353 ai值可以为0
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=2e5+5;
const int mod=998244353;
#define mp make_pair
#define fi first
#define se second
ll t,n,m,k,ans,pos;
ll a[maxn],pre[maxn],vis[maxn];
string s;
ll ksm(ll a,ll b){
ll res=1;
while(b){
if(b&1)
res=res*a%mod;
a=a*a%mod;
b>>=1;
}
return res;
}
ll inv_mod(ll a){
return ksm(a,mod-2);
}
int main(){
cin>>n>>k;
pre[0]=1;
for(int i=1;i<=n;i++){
cin>>a[i];
}
ll l=1,r=1,res=1;
for(;r<=n;){
if(a[r]==0)
{
l=r+1;
r=l;
res=1;
}
else{
res=res*a[r]%mod;
r++;
}
if(r-l==k){
ans=max(ans,res);
// cout<<l<<" "<<r<<" "<<ans<<endl;
res=res*inv_mod(a[l])%mod;
l++;
}
}
cout<<ans<<endl;
return 0;
}
线段树
#include<bits/stdc++.h>
using namespace std;
const int maxn = 2e5 + 5;
typedef long long ll;
const ll mod=998244353;
ll a[maxn];
int now;
class segment_tree {public:
#define nd node[now]
#define ndl node[now << 1]
#define ndr node[now << 1 | 1]
struct segment_node {
int l,r;
ll sum;
}node[maxn << 2];
void pushup(int now) {
nd.sum = (ndl.sum * ndr.sum)%mod;
}
void maketree(int l,int r,int now = 1) {
nd = {l,r,0};
if(l == r) {
nd.sum = a[l];
return;
}
int mid = l + r >> 1;
maketree(l,mid,now << 1);
maketree(mid+1,r,now << 1 | 1);
pushup(now);
}
ll query(int l, int r, int now = 1) {
if(l<=nd.l && r>=nd.r) return nd.sum;
ll res = 1;
if(l <= ndl.r) res = (res*query(l,r,now << 1))%mod;
if(r >= ndr.l) res = (res*query(l,r,now << 1 | 1))%mod;
return res;//不能忘
}
}tree;
int main(){
int n,m,k;
cin >> n >> k;
for(int i=1;i<=n;i++) cin >> a[i];
tree.maketree(1,n);
ll ans=0;
for(int i=1;i<=n-k+1;i++){
ans=max(ans,tree.query(i,i+k-1));
}
cout << ans << endl;
return 0;
}
A
运行速度快
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e5+5;
const int mod=1e9+7;
#define mp make_pair
#define fi first
#define se second
ll t,n,m,k,ans;
ll a[maxn],f;
string s;
int main(){
cin>>t;
while(t--){
ll x=0,y=0,t=0;
cin>>n;
if(n==0)
cout<<1<<endl;
else if(n==1)
cout<<3<<endl;
else
{
//2 1
x=2,y=1;
for(int i=2;i<=n;i++){
t=y;
y=x;
x=x+t;
}
cout<<x+y<<endl;
}
}
return 0;
}
斐波那契数列递推慢 a[n+2]+a[n+1]
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=2e5+5;
const int mod=998244353;
#define mp make_pair
#define fi first
#define se second
ll t,n,m,k,ans,pos;
ll a[maxn],pre[maxn],vis[maxn];
string s;
int main(){
a[1]=1;a[2]=1;
for(int i=3;i<=82;i++)
a[i]=a[i-1]+a[i-2];
cin>>t;
while(t--){
cin>>n;
if(n==0)
cout<<1<<endl;
else
cout<<a[n+2]+a[n+1]<<endl;
}
return 0;
}
E
5e5长度的数字爆ll
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=5e5+5;
const int mod=998244353;
#define mp make_pair
#define fi first
#define se second
string s,ans;
char c[maxn];
ll cnt,p;
string num_push(string a,string b){
ans.clear();
int lena=a.size();
int lenb=b.size();
reverse(a.begin(),a.end()); //翻转a
reverse(b.begin(),b.end()); //翻转b
int yu=0; //余数
for(int i=0;;i++){ //一直跑
if(i<lena&&i<lenb){ //如果小于a的长度,并且小于b的长度
ans+=(yu+a[i]-'0'+b[i]-'0')%10+'0'; //第几位等于a的数值加上b的数值
yu=(yu+a[i]-'0'+b[i]-'0')/10; //然后再求余数
}else if(i<lena){ //如果只小于a,说明b跑完了
ans+=(yu+a[i]-'0')%10+'0'; //只需加上a的数值加上之前的余数
yu=(yu+a[i]-'0')/10;
}else if(i<lenb){
ans+=(yu+b[i]-'0')%10+'0';
yu=(yu+b[i]-'0')/10;
}else if(yu!=0){ //都跑完了余数还不为零那么再进一位
ans+=yu%10+'0';
yu=yu/10;
}else break; //然后退出
}
reverse(ans.begin(),ans.end()); //最后翻转一下
return ans;
}
int main(){
cin>>s;
ll len=s.size();
for(int i=0;i<len;i++){
if(s[i]=='+')
cnt++;
else
c[++p]=s[i];
}
sort(c+1,c+p+1);
// for(int i=1;i<=p;i++)
// cout<<c[i];
// cout<<endl;
if(cnt==0) //0个+ 输出排序后的s
{
for(int i=1;i<=p;i++){
cout<<c[i];
}
cout<<endl;
return 0;
}
ll num=p/(cnt+1);ll res=p%(cnt+1);
ll num1=res,num2=(cnt+1)-num1;//num+1位num1g num位num2个
string t[cnt+1];
ll n=0;
for(int i=1;i<=num1;i++){
for(int j=1;j<=num+1;j++){
t[n]+=c[(j-1)*(cnt+1)+i];
}
n++;
}
for(int i=num1+1;i<=cnt+1;i++){
for(int j=1;j<=num;j++){
t[n]+=c[(j-1)*(cnt+1)+i];
}
n++;
}
ans=num_push(t[0],t[1]);
for(int i=2;i<n;i++){
ans=num_push(ans,t[i]);
}
cout<<ans<<endl;
return 0;
}