慢跑

这题完全是在针对我

还是题意没有充分理解

  • 设跑步者B 跑步如果追上A 那么A速度就降为一样 然后后面的那位C原本追不上可能就追上了
  • 如果B追不上 C不可能追上B

设每组的领跑者的位置和速度 如果他追不上前面那位或者是最后以为则为领跑者

一道模拟题居然卡那么久 哭了

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+5;
#define ll long long
ll a[maxn],b[maxn];
int main()
{ll n,t;scanf("%lld%lld",&n,&t);for(ll i=1; i<=n; ++i){scanf("%lld%lld",&a[i],&b[i]);}ll ans=n;ll pre=b[n],pos=a[n];for(ll i=n-1; i>=1; --i){if(a[i]+b[i]*t>=pos+pre*t){ans--;}else{pos=a[i];pre=b[i];}}printf("%lld\n",ans);return 0;
}

迷宫问题

  • DFS求到终点的方案数

很基础的DFS 可能写得太少都忘了

起点的标记要注意

然后每次遇到DFS都有种莫名的恐惧?

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn=102;
int s[maxn][maxn];
bool vis[maxn][maxn];
int n,ans;
int dx[]= {0,0,1,-1,1,-1,-1,1};
int dy[]= {1,-1,0,0,1,-1,1,-1};
void dfs(int x,int y){for(int i=0; i<8; ++i){int xx=x+dx[i];int yy=y+dy[i];if(xx==1&&yy==n){ans++;return;}if(xx>=1&&xx<=n&&yy>=1&&yy<=n&&!s[xx][yy]&&!vis[xx][yy]){vis[xx][yy]=true;dfs(xx,yy);vis[xx][yy]=false;}}
}
int main(){scanf("%d",&n);for(int i=1; i<=n; ++i){for(int j=1; j<=n; ++j)scanf("%d",&s[i][j]);}vis[1][1]=true;dfs(1,1);printf("%d\n",ans);return 0;
}

星区

对题意坐标的理解…..其实也很好理解

然后就是DFS求连通块

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn=55;
int s[maxn][maxn][maxn];
bool vis[maxn][maxn][maxn];
int n;int X,Y,Z,m;
int dx[]={0,0,-1,1,0,0};
int dy[]={1,-1,0,0,0,0};
int dz[]={0,0,0,0,1,-1};
void dfs(int x,int y,int z,int p){vis[x][y][z]=true;for(int i=0; i<6; ++i){int xx=x+dx[i];int yy=y+dy[i];int zz=z+dz[i];if(xx>=1&&xx<=X&&yy>=1&&yy<=Y&&zz>=1&&zz<=Z&&!vis[xx][yy][zz]&&abs(s[xx][yy][zz]-p)<=m){dfs(xx,yy,zz,s[xx][yy][zz]);}}
}
int main(){scanf("%d%d%d%d",&X,&Y,&Z,&m);for(int i=1;i<=X;++i){for(int j=1;j<=Y;++j){for(int k=1;k<=Z;++k){scanf("%d",&s[i][j][k]);}}}int ans=0;for(int i=1;i<=X;++i){for(int j=1;j<=Y;++j){for(int k=1;k<=Z;++k){if(!vis[i][j][k]){dfs(i,j,k,s[i][j][k]);ans++;}}}}printf("%d\n",ans);return 0;
}

冠军剑士

  • BFS求最短路径

这三个题算是搜索的基础题

#include <bits/stdc++.h>
#define ll long long
using namespace std;
int n,m;
int dx[]={0,0,1,-1};
int dy[]={1,-1,0,0};
int cx[]={0,0,1,-1,1,-1,1,-1};
int cy[]={1,-1,1,-1,0,0,-1,1};
bool vis[101][101];
int stx,sty,enx,eny;
inline bool check(int x,int y){if(x>=1&&x<=n&&y>=1&&y<=m) return true;return false;
}
struct node{int x,y;int step;
}st,en;
int bfs(){queue<node>que;st.x=stx;st.y=sty;vis[st.x][st.y]=true;st.step=0;que.push(st);while(!que.empty()){st=que.front();que.pop();if(st.x==enx&&st.y==eny){return st.step;}for(int i=0;i<4;++i){int xx=st.x+dx[i];int yy=st.y+dy[i];if(!vis[xx][yy]&&check(xx,yy)){en.x=xx;en.y=yy;en.step=st.step+1;vis[xx][yy]=1;que.push(en);}}}return 0;
}
int main() {int t;scanf("%d%d%d%d%d%d%d",&n,&m,&stx,&sty,&enx,&eny,&t);int u,v;for(int i=1;i<=t;++i){scanf("%d%d",&u,&v);vis[u][v]=1;for(int j=0;j<8;++j){int xx=u+cx[j];int yy=v+cy[j];if(check(xx,yy)){vis[xx][yy]=1;}}}printf("%d\n",bfs());return 0;
}

帝国交通

题意要求几个需要联系的王国之间建立最短的道路,然后道路只能建在相邻的两点,并且是环.

数组开两倍然后断环为链 这是基本操作

因为有些区间正更优,有些反过来优,通过枚举链上的起点,这样就可以枚举到所有的情况

左端点+1 右端点-1 for一遍就让res不停加上该位置的值,如果不是0则证明这段需要建路

#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=20005;
const int maxm=2000;
struct node
{int l,r;
} s[maxn];
int f[maxm];
int main(){int n,m;scanf("%d%d",&n,&m);for(int i=1; i<=m; ++i){scanf("%d%d",&s[i].l,&s[i].r);if(s[i].l>s[i].r) swap(s[i].l,s[i].r);}int ans=n;for(int i=0; i<n; ++i){int st=1+i;int en=n+i;int res=0,tmp=0;memset(f,0,sizeof(f));for(int j=1;j<=m;++j){if(s[j].l>=st){f[s[j].l]++;f[s[j].r]--;}else if(s[j].l<st&&s[j].r<st){f[s[j].l+n]++;f[s[j].r+n]--;}else if(s[j].l<st&&s[j].r>=st){f[s[j].l+n]--;f[s[j].r]++;}}for(int j=st; j<=en; ++j){res+=f[j];if(res>0){tmp++;}}ans=min(tmp,ans);}printf("%d\n",ans);return 0;
}

矩阵快速幂

设矩阵\(A\)
\[ S=A^1+A^2+A^3+....+A^n \]
直接用矩阵快速幂然后加起来肯定超时

这题可以用等比数列求和的方法 但是矩阵不能除 算逆阵有点麻烦 

把这个矩阵拆成两个部分 就是
\[ S=A^1+A^2+A^3+....+A^{n/2}+A^{n/2}*(A^1+A^2+A^3+....+A^{n/2}) \]
然后通过递归 奇数再加上\(A^{n/2+1}\)就好了

matrix expmod(matrix a,int n)//快速幂
{e.init();while (n){if(n & 1) e=e*a;a=a*a;n>>=1;}return e;
}
matrix solve(int k)//二分
{if(k==1) return a;c=solve(k>>1);matrix ans=c+c*expmod(a,(k>>1));if(k & 1) ans=ans+expmod(a,k);return ans;
}

也可以通过构造嵌套矩阵的方法来求
\[ \begin{matrix} A&A \\ 0&E \\ \end{matrix} \tag{1} \]

发财兔序列

注意审题:非降序列

记下每种数的起点 每个位置属于哪种树

查询时两边的数可以通过其到起点的距离来得出

而中间的数则转化为查询区间最大值

#include <bits/stdc++.h>
using namespace std;
const int maxn=1e5+1;
int stmax[maxn][20],stmin[maxn][20];
int poww[25],logg[maxn];
int n,q;
int findll[maxn];
int ll[maxn];
int a[maxn],cnt[maxn];
void init(){poww[0]=1;for(int i=1; i<=20; i++)//预处理次方{poww[i]=poww[i-1]<<1;}for(int i=2; i<=n; i++){logg[i]=logg[i>>1]+1;}int temp=1;for(int j=1; j<=logg[n]; j++)//temp=2^(j-1){for(int i=1; i<=n-temp-temp+1; i++){stmax[i][j]=max(stmax[i][j-1],stmax[i+temp][j-1]);}temp<<=1;}
}
inline int query_max(int l,int r){if(r<l) return 0;int len=r-l+1;int k=logg[len];return max(stmax[l][k],stmax[r-poww[k]+1][k]);
}
int main(){int num;n=0;scanf("%d",&num); scanf("%d",&q);for(int i=1;i<=num;++i){scanf("%d",&a[i]);if(a[i-1]!=a[i]||i==1){n++;cnt[n]++;findll[i]=n;ll[n]=i;}else{cnt[n]++;findll[i]=n;}}for(int i=1;i<=n;++i){stmax[i][0]=cnt[i];}init();int u,v;while(q--){scanf("%d%d",&u,&v);if(findll[u]==findll[v]){printf("%d\n",v-u+1);}else{int tmp=max(cnt[findll[u]]-u+ll[findll[u]],v-ll[findll[v]]+1);printf("%d\n",max(tmp,query_max(findll[u]+1,findll[v]-1)));}}return 0;
}

发财兔fbi树

  • 后序遍历:先左后右再到根

有点像线段树的递归

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <queue>
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn=1e6+7;
char s[1028];
void gao(int l,int r){if(r>l){gao(l,(l+r)>>1);gao(((l+r)>>1)+1,r);}int fo=0,tmp=0;for(int i=l;i<r;++i){if(s[i]!=s[i+1]){fo=1;}}if(fo){cout<<'F';}else if(!fo&&s[l]=='0'){cout<<'B';}else if(!fo&&s[l]=='1'){cout<<'I';}
}
int main(){ios::sync_with_stdio(false);cin.tie(0);int n;cin>>n;cin>>s+1;int tmp=1<<n;gao(1,tmp);return 0;
}

滑动窗口

强行用ST表水过去

实际上应该用单调队列

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn=1e6+7;
int s[maxn];int q[maxn],p[maxn],k;
void solve_max(int n){int head=1;int tail=0;for(int i=1;i<=n;++i){while(head<=tail&&q[tail]<=s[i]) tail--;q[++tail]=s[i];p[tail]=i;while(p[head]<=i-k)head++;if(i>=k)printf("%d ",q[head]);}printf("\n");
}
void solve_min(int n){int head=1;int tail=0;for(int i=1;i<=n;++i){while(head<=tail&&q[tail]>=s[i]) tail--;q[++tail]=s[i];p[tail]=i;while(p[head]<=i-k)head++;if(i>=k)printf("%d ",q[head]);}printf("\n");
}
int main(){int n;scanf("%d%d",&n,&k);for (int i = 1; i <=n ; ++i) {scanf("%d",&s[i]);}solve_min(n);memset(p,0,sizeof(p));memset(q,0,sizeof(q));solve_max(n);return 0;
}

发财兔求和

推公式,找出重复计算的部分优化

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 100000+1;
const int mod = 10007;
struct node{ll x;ll val;
}s[maxn];
ll dp[2][maxn];
ll num[2][maxn];
int main(){ll n,m;scanf("%lld%lld",&n,&m);for(ll i=1;i<=n;++i) {scanf("%lld", &s[i].val);}for(ll i=1;i<=n;++i){scanf("%lld",&s[i].x);dp[i%2][s[i].x]=(s[i].val+dp[i%2][s[i].x])%mod;num[i%2][s[i].x]=(num[i%2][s[i].x]+1)%mod;}ll ans=0;for(int i=1;i<=n;++i){ans=(ans+i*((num[i%2][s[i].x]-2)*s[i].val%mod+dp[i%2][s[i].x])%mod)%mod;}printf("%lld\n",ans);return 0;
}

有趣的数

  • 当\(n\)是10的倍数的时候,位置一定是 $\log_{10}k $,如果不是的话就返回0
  • 当n不是10的倍数:
    • 如果位置小于n为最大数时n的位置,返回0
    • 如果位置等于n为最大数时n的位置,返回n
    • 大于的话,就让len++,让n增大,模拟找到合适的位置
#include<iostream>
#include <bits/stdc++.h>
using namespace std;
#define ll long long
string a;
ll pos,s[10];
ll gao(){int len=(int)a.length();ll ans=0,p=0,log=1;for(int i=0;i<len;++i){s[i]=a[i]-'0';p=p*10ll+s[i];ans+=p-log;log*=10ll;if(i!=len-1) ans++;}//ans为比n小的有多少if(ans+1==pos)return p;if(p*10==log)return 0;if(pos<ans+1) return 0;while(1){p*=10ll;if(ans+1+p-log>=pos){return log+pos-ans-2;}//pos-(ans+1)是差多少位 加上log-1就是答案ans+=p-log;log*=10ll;}
}
int main(){ios::sync_with_stdio(false);cin.tie(0);int t;cin>>t;while(t--){cin>>a>>pos;cout<<gao()<<endl;}return 0;
}

matrix

神奇的暴力瞎搞

行与行之间可以相互交换 枚举列 那么每行只用在意当前列有没有1 1最多能延伸多少

#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=5000+5;
bool arr[maxn][maxn];
int cnt[maxn];
int ans;char str;
int pos[maxn];int n,m;
inline void gao(){for(register int i=m;i>=1;--i){ans=max(ans,i*cnt[i]);cnt[i-1]+=cnt[i];cnt[i]=0;}
}
int main(){ios::sync_with_stdio(false);cin.tie(0);cin>>n>>m;for(int i=1;i<=n;++i){for(int j=1;j<=m;++j){cin>>str;if(str=='0')arr[i][j]=0;else arr[i][j]=1;}}for(register int j=1;j<=m;++j){for(register int i=1;i<=n;++i){if(!arr[i][j]) continue;if(pos[i]<j)pos[i]=j;while(pos[i]<=m&&arr[i][pos[i]+1]) pos[i]++;cnt[pos[i]-j+1]++;}gao();}cout<<ans<<endl;return 0;
}

发财兔1C

[l,r]内的卡片所有出现了偶数次的数的异或和是多少

可以转化为区间不同的数的个数与区间所有数的异或和

因为如果一个数出现偶数次 那么这个数异或和为0,奇数则为原来的数

这样就会把原序列中奇数个数的数都去掉

区间不同数通过离线查询,记录这个数最后出现的位置,然后树状数组来实现

#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=1e6+5;
int pre_sum[maxn],unq_sum[maxn],n,q;
inline int lowbit(int x){return x&(-x);
}
ll getsum(int pos){ll res=0;for(ll i=pos;i>0;i-=lowbit(i)){res^=unq_sum[i];}return res;
}
void add(int pos,int val){for(int i=pos;i<=n;i+=lowbit(i)){unq_sum[i]^=val;}
}
struct node{int l,r,id;bool operator<(const node &c)const{return r<c.r;}
}s[maxn];
struct find_last{int val,id;bool operator<(const find_last &c)const{if(val==c.val){return id<c.id;}else return val<c.val;}
}copy_num[maxn];
int num[maxn];
int last[maxn];
int ans[maxn];
int main(){scanf("%d%d",&n,&q);for(int i=1;i<=n;++i){scanf("%d",&num[i]);copy_num[i].val=num[i];copy_num[i].id=i;pre_sum[i]=pre_sum[i-1]^num[i];}for(int i=1;i<=q;++i){scanf("%d%d",&s[i].l,&s[i].r);s[i].id=i;}sort(s+1,s+1+q);int pos=1;sort(copy_num+1,copy_num+n+1);for(int i=2;i<=n;++i){if(copy_num[i].val==copy_num[i-1].val){last[copy_num[i].id]=copy_num[i-1].id;}}for(int z=1;z<=q;++z){while(pos<=s[z].r){if(last[pos]) add(last[pos],num[pos]);add(pos,num[pos]);pos++;}ans[s[z].id]=getsum(s[z].r)^getsum(s[z].l-1)^pre_sum[s[z].r]^pre_sum[s[z].l-1];}for(int i=1;i<=q;++i){printf("%d\n",ans[i]);}return 0;
}

桥桥的告白

审题 充分理解题意

记录过程 然后向上递归查询a喜欢b b喜欢c c喜欢d之类的

找到最原始被喜欢的那个人

#include<string>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
using namespace std;
#define ll long long
const int maxn=1005;
const int maxm=300000+1;
int pos[maxm][2];
int main(){ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);int n;cin>>n;char s[maxn][25];for(register int i=1;i<=n;++i){cin>>s[i];}int m;cin>>m;for(register int i=1;i<=m;++i){cin>>pos[i][0]>>pos[i][1];}int pre=1;for(register int i=m;i>=1;--i){if(pos[i][0]==pre){pre=pos[i][1];cout<<"I_love_";}}cout<<s[pre]<<endl;return 0;
}

菱菱的旅途

贪心策略

左右端点 先缩小的那个端点 然后找到最大值

因为缩小小的必然优于缩大的 然后就可以不重不漏找到枚举所有可能情况

#include<string>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
using namespace std;
#define ll long long
const int maxn=1000000+5;
ll s[maxn];
int main()
{int n;scanf("%d",&n);for(int i=1; i<=n; ++i) scanf("%lld",&s[i]);ll l=1,r=n;if(n==1) printf("%lld\n",s[1]);else{ll ans=min(s[1],s[n])*n;while(l<=r){if(s[l]<=s[r]) l++;else if(s[l]>s[r])r--;ans=max(min(s[l],s[r])*(r-l+1),ans);}printf("%lld\n",ans);}return 0;
}

鑫鑫的算术

跟a and b和a or b有关的题要联想到二进制

可以发现这个单纯是二进制1的重组 如何让1重组成最大的数 当然是每位尽量都是1

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int mod=998244353;
int wei[35];
ll p_pow[35];
void count_one(int n){int res=0;while(n){if(n&1) wei[res]++;n>>=1;res++;}
}
void init(){p_pow[0]=1;for(int i=1;i<=32;++i){p_pow[i]=p_pow[i-1]*2ll;}
}
ll gao(){bool flag=0;ll res=0;for(int i=32;i>=0;--i){if(wei[i]){flag=1;res=res+p_pow[i];wei[i]--;if(res>=mod) res-=mod;}}if(flag==0) return -1;return res;
}
int main(){int n;scanf("%d",&n);int a;init();for(int i=1;i<=n;++i){scanf("%d",&a);count_one(a);}ll ans=0;ll tmp=gao();while(tmp!=-1){ans+=tmp*tmp%mod;if(ans>=mod) ans-=mod;tmp=gao();}printf("%lld\n",ans%mod);return 0;
}

排队

由题意可知,可以分成很多个链.枚举x所在的链前面有多少链,然后得到可能的位置

可以用dp来求,也可以用bitset这个骚操作

#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn = 1005;
int n,x,fa[maxn];
bool vis[maxn];
int main(){scanf("%d%d",&n,&x);for(int i=1;i<=n;++i){scanf("%d",&fa[i]); vis[fa[i]]=true;}int res,p,flag;vector<int>vt;for(int i=1;i<=n;++i){if(vis[i])continue;else{res=0;p=i;flag=0;while(p){res++;flag|=(x==p);p=fa[p];}if(!flag) vt.push_back(res);}}bitset<maxn>dp; dp[0]=1;for(auto x:vt)  dp|=(dp<<x);p=x;int c=0;while(p){c++;p=fa[p];}for(int i=0;i<=n;++i){if(dp[i]) printf("%d\n",i+c);}return 0;
}

DAVE打扑克

两堆合并用并查集

虽然堆数可能很多,但是不同数量堆最多有1e3个

cnt[i]记录牌数为i的有多少个

相同牌数的贡献是cnt[i] * (cnt[i]-1)/2

不同牌数的贡献是cnt[i] * cnt[j]

#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=1e5+7;
ll n,m;
ll fa[maxn];
set<ll>st;
ll val[maxn];
ll cnt[maxn];
ll que[maxn*5];
ll Size;
ll findfa(ll x){if(fa[x]==x) return x;else return fa[x]=findfa(fa[x]);
}
void add(ll u,ll v){ll f1=findfa(u);ll f2=findfa(v);if(f1!=f2){cnt[val[f1]]--;cnt[val[f2]]--;if(!cnt[val[f1]]) st.erase(val[f1]);if(!cnt[val[f2]]) st.erase(val[f2]);fa[f1]=f2;val[f2]+=val[f1];cnt[val[f2]]++;st.insert(val[f2]);Size--;}
}
int main(){scanf("%lld%lld",&n,&m);for(ll i=1;i<=n;++i){fa[i]=i;val[i]=1;}cnt[1]=n;st.insert(1);ll op,pos,u,v;Size=n;for(ll i=1;i<=m;++i){scanf("%lld",&op);if(op==1){scanf("%lld%lld",&u,&v);add(u,v);}else{scanf("%lld",&pos);set<ll>::iterator it=st.begin();ll tail=0,head=0,pre=0;ll ans=0;while(it!=st.end()){while(head<tail&& *it-que[head]>=pos){pre-=cnt[que[head]];head++;}ans+=cnt[*it]*pre;if(pos>0) ans+=(cnt[*it]*(cnt[*it]-1))/2;que[tail++]=*it;pre+=cnt[*it];it++;}printf("%lld\n",Size*(Size-1)/2-ans);}}return 0;
}

You Like the Cake

对于100的数据,N≤40,X,Vi≤109

背包容量过大采用折半之后二进制枚举子集,再二分查找

upper_bound返回的是第一个大于查找的数的位置

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
ll a[25],b[25];
ll s[(1<<21)+1],f[(1<<21)+1];
int main(){int n;ll m;scanf("%d%lld",&n,&m);for(int i=1;i<=n;++i){if(i<=n/2){scanf("%lld",&a[i]);}else scanf("%lld",&b[i-n/2]);}int k=n/2;int pos=0;for(int i=0;i<(1<<k);++i){for(int j=1;j<=k;++j){if(i&(1<<(j-1))){s[pos]+=a[j];}}pos++;}int len=(int)(unique(s,s+pos)-s);sort(s,s+len);pos=0;k=n-k;for(int i=0;i<(1<<k);++i){for(int j=1;j<=k;++j){if(i&(1<<(j-1))){f[pos]+=b[j];}}pos++;}ll ans=0;int op;for(int i=0;i<pos;++i){if(m<f[i]) continue;op=upper_bound(s,s+len,m-f[i])-s;op--;if(op>=0){ans=max(ans,s[op]+f[i]);}}printf("%lld\n",m-ans);return 0;
}

刚开始感觉是组合数学…没想到是跟喝汤差不多的一道DP.

#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5+10;
#define ll long long
ll dp[maxn][4][2];
const int mod=1e9+7;
void init(ll s){memset(dp,0,sizeof(dp));dp[1][1][0]=s;
}
int main(){int t;scanf("%d",&t);while(t--) {ll n, s;scanf("%lld%lld", &n, &s);init(s);for(int i=2;i<=n;++i){dp[i][1][0]=(dp[i-1][1][0]*(s-1)%mod+dp[i-1][2][0]*(s-1)%mod)%mod;dp[i][2][0]=dp[i-1][1][0];dp[i][3][1]=dp[i-1][2][0];dp[i][1][1]=((dp[i-1][1][1]*(s-1)%mod+dp[i-1][2][1]*(s-1)%mod)%mod+dp[i-1][3][1]*(s-1)%mod)%mod;dp[i][2][1]=dp[i-1][1][1];}ll res=0;res=((dp[n][1][1]+dp[n][2][1])%mod+dp[n][3][1])%mod;printf("%lld\n",res);}return 0;
}

五子棋

模拟 斜线那个注意一下.

#include <bits/stdc++.h>
using namespace std;
int mapp[250][250];
bool check_updown(int x,int y)
{int sum=1;for(int i=x+1;i<=225;++i){if(mapp[x][y]==mapp[i][y]) sum++;else break;}for(int i=x-1;i>=1;--i){if(mapp[x][y]==mapp[i][y]) sum++;else break;}if(sum>=5) return 1;return 0;
}
bool check_rightle(int x,int y)
{int sum=1;for(int i=y+1;i<=225;++i){if(mapp[x][y]==mapp[x][i]) sum++;else break;}for(int i=y-1;i>=1;--i){if(mapp[x][y]==mapp[x][i]) sum++;else break;}if(sum>=5) return 1;return 0;
}
bool check_rightxie(int x,int y)
{int sum=1;for(int i=1;x+i<=225&&y+i<=225;++i){if(mapp[x][y]==mapp[x+i][y+i]) sum++;else break;}for(int i=1;x-i>=1&&y-i>=1;++i){if(mapp[x][y]==mapp[x-i][y-i]) sum++;else break;}if(sum>=5) return 1;return 0;
}
bool check_leftxie(int x,int y)
{int sum=1;for(int i=1;x+i<=225&&y-i>=1;++i){if(mapp[x][y]==mapp[x+i][y-i]) sum++;else break;}for(int i=1;x-i>=1&&y+i<=225;++i){if(mapp[x][y]==mapp[x-i][y+i]) sum++;else break;}if(sum>=5) return 1;return 0;
}
int check_all(int x,int y)
{if(check_leftxie(x,y)||check_updown(x,y)||check_rightle(x,y)||check_rightxie(x,y)){return 1;}return 0;
}
int main()
{int t;scanf("%d",&t);int x,y;int flag=0;for(int i=1; i<=t; ++i){scanf("%d%d",&x,&y);if(flag) continue;if(i%2==1){mapp[x][y]=1;}else{mapp[x][y]=2;}if(check_all(x,y)){flag=i;}}if(!flag) puts("Tie");else{if(flag&1) printf("A ");else printf("B ");printf("%d\n",flag);}return 0;
}

凉宫春日的忧郁

取对数…..

#include <bits/stdc++.h>
const double eps=1e-6;
using namespace std;int main()
{int t;cin>>t;while(t--){double n,m;cin>>n>>m;double a=1,b=0;a=m*log10(n);for(int i=1; i<=m; ++i){b+=log10(i);}if(a-b>=eps){puts("No");}else puts("Yes");}return 0;
}

Back and Forth

想练一下DFS 结果题意被别人误导…..

#include <bits/stdc++.h>
const double eps=1e-6;
using namespace std;
int a[12],b[12],ans;
int tmp;
map<int,int>mp;
int sum;
void dfs(int now,int p,int pre){if(now==1){tmp=ans;tmp-=a[p];b[11]=a[p];a[p]=0;for(int j=1;j<=11;++j){if(b[j])dfs(2,j,p);}a[p]=b[11];}if(now==2){tmp+=b[p];a[pre]=b[p];b[p]=0;for(int i=1;i<=10;++i){if(a[i])dfs(3,i,p);}b[p]=a[pre];tmp-=b[p];}if(now==3){tmp-=a[p];b[pre]=a[p];a[p]=0;for(int i=1;i<=11;++i){if(b[i])dfs(4,i,p);}a[p]=b[pre];tmp+=a[p];}if(now==4){if(!mp[tmp+b[p]]){mp[tmp+b[p]]=1;sum++;}}
}
int main(){for(int i=1;i<=10;++i){scanf("%d",&a[i]);}ans=1000;for(int i=1;i<=10;++i){scanf("%d",&b[i]);}for(int i=1;i<=10;++i){dfs(1,i,0);}printf("%d",sum);return 0;
}

[DP]烤乐滋喝汤

一个很简单的DP.就是有一种情况他可能前面的都不管然后直接下药没考虑到.

#include <bits/stdc++.h>
#define ll long long
#define ull unsigned long long
#define mp make_pair
#define met(a,x) memset(a,x,sizeof(a))
using namespace std;
const int maxn=1e5+7;
ll dp[maxn][2];
const int inf=0x3f3f3f3f;
int main()
{ll n,m;scanf("%lld%lld",&n,&m);ll ans=-inf;ll s;memset(dp,0,sizeof(dp));for(int i=1; i<=n; ++i){scanf("%lld",&s);if(i==1){dp[i][0]=s;dp[i][1]=max(dp[i-1][0]+m,m);}else{dp[i][0]=max(s,dp[i-1][0]+s);dp[i][1]=max(max(dp[i-1][0]+m,dp[i-1][1]+s),m);}ans=max(ans,dp[i][1]);}printf("%lld\n",ans);return 0;
}

[取模运算]阿卡吃馅饼

一直想着怎么把数弄得很大,忘记取摸这个操作

#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=1e5+7;
ll qpow(ll a,ll n,ll mod){ll res=1;while(n){if(n&1){res*=a;res%=mod;}n>>=1;a=(a*a)%mod;}return res;
}int main(){int n;scanf("%d",&n);while(n--) {int t, r;scanf("%d%d", &t, &r);int ans=0,i;for(i=0;i<=1000;++i){ans=(ans+qpow(10,i,r)*t%r)%r;if(ans==0) break;}if(i==1001){puts("GG");}else printf("%d\n",i);}
}

[求回文串个数]大战幻想珠

两种情况

一个是从奇数出发,一个是从偶数出发

当出现?直接相等就好

#include <bits/stdc++.h>
#define ll long long
#define inf 0x3f3f3f3f
#define ull unsigned long long
#define mp make_pair
#define met(a,x) memset(a,x,sizeof(a))
using namespace std;
const int maxn=1e5+7;
string s;
int n;ll gao(){ll ans = 0;for (register int i=0; i<n;++i){for (register int j=0; i+ j <n && i-j>=0 ; ++j){if(s[i-j]==s[i+j]||s[i-j]=='?'||s[i+j]=='?')ans++;else break;}for (register int j=0; i + j <n && i-1-j>=0; ++j){if(s[i-1-j]==s[i+j]||s[i-1-j]=='?'||s[i+j]=='?')ans++;else break;}}return ans;
}
int main(){cin>>n;cin>>s;cout<<gao()<<endl;return 0;
}

[暴力枚举]烤乐滋打虎

#include <bits/stdc++.h>
#define ll long long
#define ull unsigned long long
#define mp make_pair
#define met(a,x) memset(a,x,sizeof(a))
using namespace std;
int s[101];
int d[101][101];
const int inf=0x3f3f3f3f;
int main()
{int n;scanf("%d",&n);for(int i=1; i<=n; ++i){scanf("%d",&s[i]);}for(int i=2; i<=n; ++i){scanf("%d",&d[i][i-1]);d[i-1][i]=d[i][i-1];}int ans=inf,tmp;for(int i=1; i<=n; ++i){int t=0;tmp=0;if(i!=n){for(int j=i; j<=n; ++j){tmp+=s[j]+t;t+=d[j][j+1];}int p=i-1;t*=2;t+=d[p][i];for(int j=p; j>=1; --j){tmp+=s[j]+t;t+=d[j][j-1];}ans=min(ans,tmp);//cout<<ans<<" "<<i<<endl;}if(i!=1){t=0;tmp=0;for(int j=i; j>=1; --j){tmp+=s[j]+t;t+=d[j][j-1];}t*=2;t+=d[i][i+1];for(int j=i+1; j<=n; ++j){tmp+=s[j]+t;t+=d[j][j+1];}ans=min(ans,tmp);//cout<<ans<<" "<<i<<endl;}}printf("%d\n",ans);return 0;
}

旅程

先删掉一条边(赋值为INF)

跑FLOYD 记录询问 从后往前 

遇到删边操作则枚举起点和终点\(n^2\)暴力更新答案

#include <iostream>
#include <bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn=205;
int d[maxn][maxn];
int dis[maxn][maxn];
int n,m;
void floyd(){for(int k=1;k<=n;++k){for(int i=1;i<=n;++i){for(int j=1;j<=n;++j){d[i][j]=min(d[i][j],d[i][k]+d[k][j]);}}}
}
struct node{int u,v,op,val;
}s[100000+1];
void gao(int k){int u=s[k].u;int v=s[k].v;int val=min(d[u][v],dis[u][v]);for(int i=1;i<=n;++i){for(int j=1;j<=n;++j){d[i][j]=min(d[i][j],d[i][u]+val+d[v][j]);}}
}
int vis[maxn][maxn];
int main(){scanf("%d%d",&n,&m);for(int i=1;i<=n;++i){for(int j=1;j<=n;++j){scanf("%d",&dis[i][j]);d[i][j]=dis[i][j];}}for(int i=1;i<=m;++i){scanf("%d%d%d",&s[i].op,&s[i].u,&s[i].v);if(s[i].op==1){s[i].val=d[s[i].u][s[i].v];d[s[i].u][s[i].v]=1e9;vis[s[i].u][s[i].v]++;}}floyd();vector<int>vt;for(int i=m;i>=1;--i){if(s[i].op==2){vt.push_back(d[s[i].u][s[i].v]);}else {--vis[s[i].u][s[i].v];if(!vis[s[i].u][s[i].v]){gao(i);}}}int len=(int)vt.size();for(int i=len-1;i>=0;--i){if(vt[i]>=1e9) puts("-1");else  printf("%d\n",vt[i]);}return 0;
}

子序列

数组数组求逆序数模板题

记住相同数的处理和相同和离散化

#include <bits/stdc++.h>
#define ll long long
using namespace std;
int n;
const int maxn=2e5+7;
ll c[maxn];
const int mod=1e9+7;
int lowbit(int i) {return i&(-i);}
ll pre_min[maxn],pre_max[maxn];
ll las_min[maxn],las_max[maxn];
int num[maxn];
int b[maxn];
ll sum(int x){ll res=0;for(int i=x;i>0;i-=lowbit(i)){res+=c[i];}return res;
}
void add(int x,ll val){for (int i =x; i <=n ; i+=lowbit(i)) {c[i]+=val;}
}
struct node{ll val;int id;
}s[maxn];
bool cmp(node a,node b){if(a.val==b.val) return a.id<b.id;return a.val<b.val;
}
int main() {scanf("%d",&n);for(int i=1;i<=n;++i){scanf("%lld",&s[i].val);c[i]=0;s[i].id=i;}sort(s+1,s+1+n,cmp);b[s[1].id]=1;for(int i=2;i<=n;++i){if(s[i].val!=s[i-1].val)b[s[i].id]=b[s[i-1].id]+1;else if(s[i].val==s[i-1].val)b[s[i].id]=b[s[i-1].id];}for(int i=1;i<=n;++i){add(b[i],1);pre_max[i]=i-sum(b[i]);pre_min[i]=(i-1-num[b[i]])-pre_max[i];num[b[i]]++;}reverse(b+1,b+1+n);memset(c,0,sizeof(c));memset(num,0,sizeof(num));for(int i=1;i<=n;++i){add(b[i],1);las_max[n-i+1]=sum(n)-sum(b[i]);las_min[n-i+1]=(i-1-num[b[i]])-las_max[n-i+1];num[b[i]]++;}ll ans=0;for(int i=2;i<n;++i){ans=(ans+pre_max[i]*las_min[i]%mod)%mod;ans=(ans+pre_min[i]*las_max[i]%mod)%mod;// cout<<i<<" "<<pre_max[i]<<" "<<las_min[i]<<endl;// cout<<i<<" "<<pre_min[i]<<" "<<las_max[i]<<endl;}printf("%lld\n",ans);return 0;
}

转载于:https://www.cnblogs.com/smallocean/p/10392491.html

[补题]2019寒假集训相关推荐

  1. 2019寒假集训新生考试 【持续更新中】

    2019寒假集训新生考试-NEFU 0107 emoji表情包 Problem A nefu 2101 28的因子 ⭐️ 本题使用暴力枚举,统计n可以分成几个4和7, 为了防止TLE ,先统计4的个数 ...

  2. 2019寒假集训第五场(新生场)中石油补题和题解

    这场比赛本来我都出去了,然后看到老师发消息又回来了= = 然后做着做着正好mhr大佬在外面有一些事情突然没法比赛,于是就帮他交了两道题看看对不对,便于之后补题,然后还真都对了,下面是题目和解析: 问题 ...

  3. 2019寒假集训新生考试

    序言: 为期一周的欢乐的寒假集训终于结束了,很高兴能认识这么多的大佬和学长.学姐.很感谢ljw学长和陈宇老师为我们寒假培训所作出的贡献. 简单点评一下今天的考试试题,就在比赛前的中午,jlw学长说题目 ...

  4. 2019暑期个人排位集训补题--思维题

    2019暑期集训思维相关补题集 CodeForces - 768B Code For 1 Gym - 100066B CodeForces - 768B Code For 1 Jon fought b ...

  5. [nk] 2022牛客寒假算法基础集训营1 补题|题解

    目录 前言 L.牛牛学走路 MyCode OtherCode J.小朋友做游戏 MyCode A.九小时九个人九扇门 MyCode F. 中位数切分 MyCode 前言 根据难度系数补题,大概会补 A ...

  6. 2020牛客国庆集训派对day2 补题J

    2020牛客国庆集训派对day2 补题J:VIRUS OUTBREAK 题目描述 The State Veterinary Services Department recently reported ...

  7. 2019 Multi-University Training Contest 7 部分补题

    2019 Multi-University Training Contest 7 部分补题 这场比赛三个人一起组队,比赛期间自己感觉并没有奉献多少东西,所以补题.而且总感觉比赛到后期很乏力(没力气那种 ...

  8. Good Bye 2019补题记录

    Good Bye 2019补题记录 A. Card Game 题目描述 Two players decided to play one interesting card game. There is ...

  9. 2019/1/30 寒假集训总结

    从一月16号到一月29号为期两周的寒假集训已经结束了,说实话,从一开始认真对待,到最后几天出现了松懈,但仍然坚持下来.总是感觉这次集训自己做了很大的努力,直到昨天看见老费发的一篇关于去参加CCPC   ...

最新文章

  1. 查看mysql8日志_mysql8 参考手册--通用查询日志
  2. 恶意软件伪装成系统更新,通杀Win Mac Linux三大系统,隐藏半年才被发现
  3. python3下载文件-使用Python 3从网上下载文件
  4. 小熊派4G cat1模块体验测试报告,AT命令发送短信拨号无脑教程,cat1移动网速测试...
  5. php 405跳转,php – 返回HTTP 405的CORS预检请求
  6. vim查找关键字_vim常用命令及操作
  7. 计算机指令就是一串开关吗,什么是非法关机?常按计算机开关,还是直接拔掉电源插头才算啊?...
  8. php程序员试卷无答案,2019年最新PHP经典面试题及答案,PHP程序员必看
  9. cookie、session、sessionid 与jsessionid之间的关系
  10. BZOJ2005 [NOI2010]能量采集
  11. java小白必看:如何用java创建一个窗口
  12. 法院拍卖房产税费由谁承担
  13. 刘彬20000词汇03
  14. 3d编辑器的gizmo的缩放计算
  15. 64位系统最大支持多少内存
  16. HDU1087 噜啦啦卢
  17. Javascript 判断一个数是否为素数的三种解法
  18. collectingAndThen​
  19. FMODxUnity联动的声音设计
  20. 基于STC89C52RC模块的巡线小车

热门文章

  1. polygon 填充文本_如何创建(动画)文本填充
  2. 无线投屏器台湾NCC认证流程介绍
  3. iOS完美实现微信朋友圈视频截取
  4. Java Array.sort 根据字符串长度排序
  5. 将List转换为数组
  6. 国网GIM设备三维模型要求细则 - GIS
  7. 计算机睡眠但不关闭网络,win7电脑睡眠不关闭网络技巧分享
  8. LoadRunner打开IE8后报错
  9. linux用wubi安装ubuntu,硬盘Wubi方式安装Ubuntu Linux体验
  10. 中冠百年|家庭理财如何正确规划