AGC 019
来源:互联网 发布:node readfilesync 编辑:程序博客网 时间:2024/05/16 11:35
A
贪心搞一下就行了吧
B
如果翻转的一段串i~j,有s[i]=s[j](两端相等,那么他翻转的效果和i+1~j-1是一样的,所以我们只对s[i]≠s[j]的段i~j翻转,手玩一下发现翻转的结果一定是互不相同的,所以就统计一下有多少对(i,j)满足i< j且s[j]≠s[j],加上原串就是答案
code:
#include<set>#include<map>#include<deque>#include<queue>#include<stack>#include<cmath>#include<ctime>#include<bitset>#include<string>#include<vector>#include<cstdio>#include<cstdlib>#include<cstring>#include<climits>#include<complex>#include<iostream>#include<algorithm>#define ll long long#define inf 1e9+1using namespace std;const int maxn = 210000;int n;char str[maxn];int sum[30];ll ans;int main(){ scanf("%s",str); n=strlen(str); ans=1; for(int i=0;i<n;i++) { ans+=(ll)i-sum[str[i]-'a']; sum[str[i]-'a']++; } printf("%lld\n",ans); return 0;}
C
首先没有必要为了不走或少走半圆而绕格子,容易发现这样不会更优(每行每列只有一个喷泉
所以在无视喷泉的情况下我们一定是挑某一条起点到终点的最短路
然后我们目的是使在(sx,sy)到(ex,ey)的路径上经过的1/4个环尽可能多,1/2个环尽可能少
对于1/4个环,按行(或列)排序后发现找个LIS就完事了,这样肯定是最多的
同时可以构造一下走法,发现只有LIS长度=起点和终点间的行数或列数时,一定要走1个1/2的环,特判一下
code:
#include<set>#include<map>#include<deque>#include<queue>#include<stack>#include<cmath>#include<ctime>#include<bitset>#include<string>#include<vector>#include<cstdio>#include<cstdlib>#include<cstring>#include<climits>#include<complex>#include<iostream>#include<algorithm>#define ll long longusing namespace std;const int maxn = 210000;const double pi = acos(-1);int n;struct node{int x,y;}a[maxn]; int cnt;inline bool cmp(const node x,const node y){return x.x<y.x;}int sx,sy,ex,ey;int t[maxn],tp;int main(){ scanf("%d%d%d%d",&sx,&sy,&ex,&ey); bool tx=false,ty=false; if(sx>ex) swap(sx,ex),tx=true; if(sy>ey) swap(sy,ey),ty=true; scanf("%d",&n); for(int i=1;i<=n;i++) { int x,y; scanf("%d%d",&x,&y); if(sx<=x&&x<=ex&&sy<=y&&y<=ey) a[++cnt]=(node){x,y}; } for(int i=1;i<=cnt;i++) { if(tx) a[i].x=sx+(ex-a[i].x); if(ty) a[i].y=sy+(ey-a[i].y); }sort(a+1,a+cnt+1,cmp); for(int i=1;i<=cnt;i++) { if(!tp) t[++tp]=a[i].y; else { int l=1,r=tp; while(l<=r) { int mid=l+r>>1; if(t[mid]<a[i].y) l=mid+1; else r=mid-1; }++r; t[r]=a[i].y; if(t[tp+1]) ++tp; } } double ans=100.0*(ex-sx+ey-sy)+5*pi*tp-20.0*tp; if(tp==ex-sx+1||tp==ey-sy+1) ans+=5*pi; printf("%.15lf\n",ans); return 0;}
D
考虑最后和B串匹配的A串,是原来的A串左旋或右旋若干个单位得到的,右旋的我们可以将两个串都反过来做左旋,所以这里我们只考虑左旋
对于A串某个位置p,左旋i个单位后与B串的位置r对应,如果他和r位置不同,就一定对他需要至少一次filp操作,同时,如果他在转的过程中没有遇到B串的1,我们需要在左旋到目标位置后再左旋或旋之前右旋使他遇到某个B串为1的位置,分别记需要额外旋转left,right次
那么就是对每个这样的位置选择left or right使得(maxleft+maxright)*2最小
排个序弄个后缀max搞一下
复杂度n^2logn
code:
#include<set>#include<map>#include<deque>#include<queue>#include<stack>#include<cmath>#include<ctime>#include<bitset>#include<string>#include<vector>#include<cstdio>#include<cstdlib>#include<cstring>#include<climits>#include<complex>#include<iostream>#include<algorithm>#define ll long long#define inf 1e9using namespace std;inline void up(int &x,const int &y){if(x<y)x=y;}inline void down(int &x,const int &y){if(x>y)x=y;}const int maxn = 11000;int n;char s1[maxn],s2[maxn];int pre1[maxn],pre2[maxn],topre[maxn],nex[maxn];int cal(const int x,const int y){ if(x<y) return pre2[x]+pre2[n]-pre2[y-1]; else return pre2[x]-pre2[y-1];}int find_pre(const int x){ if(topre[x]) return x-topre[x]; else return x+n-topre[n];}int find_nex(const int x){ if(nex[x]!=n+1) return nex[x]-x; else return nex[1]+n-x;}struct node{int left,right;}t[maxn]; int tp,mx[maxn];inline bool cmp(const node x,const node y){return x.left<y.left;}int solve(){ int re=inf; for(int i=0;i<n;i++) { int now=0; tp=0; for(int j=1;j<=n;j++) { int r=j-i<=0?j-i+n:j-i; if(s1[j]!=s2[r]) { now++; if(s1[j]=='0') continue; if(cal(j,r)==0) t[++tp]=(node){find_pre(r),find_nex(j)}; } } sort(t+1,t+tp+1,cmp); int cost; mx[tp+1]=0; for(int j=tp;j>=1;j--) mx[j]=max(mx[j+1],t[j].right); cost=mx[1]*2; for(int j=1;j<=tp;j++) { int k=j+1;for(;k<=tp&&t[k].left==t[j].left;k++);k--; down(cost,2*(t[j].left+mx[k+1])); j=k; } if(!tp) cost=0; down(re,now+cost+i); } return re;}int main(){ scanf("%s",s1+1); scanf("%s",s2+1); n=strlen(s1+1); for(int i=1;i<=n;i++) pre1[i]=pre1[i-1]+(s1[i]-'0'), pre2[i]=pre2[i-1]+(s2[i]-'0'); for(int las=0,i=1;i<=n;i++) { if(s2[i]=='1') las=i; topre[i]=las; } for(int las=n+1,i=n;i>=1;i--) { if(s2[i]=='1') las=i; nex[i]=las; } if(pre1[n]&&!pre2[n]) {puts("-1");return 0;} int ans=solve(); for(int i=1;i*2<=n;i++) swap(s1[i],s1[n-i+1]), swap(s2[i],s2[n-i+1]); for(int i=1;i<=n;i++) pre1[i]=pre1[i-1]+(s1[i]-'0'), pre2[i]=pre2[i-1]+(s2[i]-'0'); for(int las=0,i=1;i<=n;i++) { if(s2[i]=='1') las=i; topre[i]=las; } for(int las=n+1,i=n;i>=1;i--) { if(s2[i]=='1') las=i; nex[i]=las; } down(ans,solve()); printf("%d\n",ans); return 0;}
E
假设已经匹配好了(ai,bi),我们来计算合法的交换方案
对应到一个n个点的有向图上,每一对匹配,连边ai->bi
发现根据度数分类图中有4类点,对应AB串是00,01,10,11
图中不同的联通块,交换次序互不影响
对于每个联通块,只有3种情况
若它是孤立的点,对答案无影响
若它是一个环,交换顺序任意,因为始终是1和1交换
若它是一条链,只有一种交换顺序
我们记01点和10点的数量为e,11点的数量为m
图中一定会有e条链,若干个由11点组成的环
令f[i][j]表示j个11点分到i条链的方案数
有
化一下柿子,移项,得到
快速幂套个NTT,
code:
#include<set>#include<map>#include<deque>#include<queue>#include<stack>#include<cmath>#include<ctime>#include<bitset>#include<string>#include<vector>#include<cstdio>#include<cstdlib>#include<cstring>#include<climits>#include<complex>#include<iostream>#include<algorithm>#define ll long longusing namespace std;const int maxn = 110000;const ll Mod = 998244353;ll pw(ll x,ll k){ ll re=1ll; for(;k;k>>=1,x=x*x%Mod) if(k&1) re=re*x%Mod; return re;}ll si[maxn],sN[maxn],Ni[maxn];void pre(){ si[0]=1ll;for(ll i=1;i<maxn;i++) si[i]=si[i-1]*i%Mod; sN[maxn-1]=pw(si[maxn-1],Mod-2); for(ll i=maxn-2;i>=0;i--) sN[i]=sN[i+1]*(i+1)%Mod; for(ll i=1;i<maxn;i++) Ni[i]=sN[i]*si[i-1]%Mod;}ll C(const int i,const int j){return si[i]*sN[j]%Mod*sN[i-j]%Mod;}int N,ln;ll g[maxn]; int id[maxn];void DFT(ll s[],int sig,int nown){ for(int i=0;i<nown;i++) if(i<id[i]) swap(s[i],s[id[i]]); int kk=N/nown; for(int m=2;m<=nown;m<<=1) { int t=m>>1,tt=nown/m; for(int j=0;j<nown;j+=m) { for(int i=0;i<t;i++) { ll wn=sig==1?g[i*tt*kk]:g[(nown-i*tt)*kk]; ll tx=s[j+i],ty=s[j+i+t]*wn%Mod; s[j+i]=(tx+ty)%Mod; s[j+i+t]=(tx-ty+Mod)%Mod; } } } if(sig==-1) for(int i=0;i<nown;i++) (s[i]*=Ni[nown])%=Mod;}ll f[maxn];int n,m,e;void FFT(ll s[]){ //for(int i=0;i<N;i++) printf("%lld ",s[i]); puts(""); DFT(s,1,N); for(int i=0;i<N;i++) s[i]=s[i]*s[i]%Mod; DFT(s,-1,N); //for(int i=0;i<N;i++) printf("%lld ",s[i]); puts(""); for(int i=m+1;i<N;i++) s[i]=0;}ll temp[maxn];void get_f(ll f[],int k){ temp[0]=si[m]; for(;k;k>>=1,FFT(f)) if(k&1) { DFT(temp,1,N); DFT(f,1,N); for(int i=0;i<N;i++) temp[i]=temp[i]*f[i]%Mod; DFT(temp,-1,N); DFT(f,-1,N); for(int i=m+1;i<N;i++) temp[i]=0; } for(int i=0;i<N;i++) f[i]=temp[i];}void solve(){ for(int i=0;i<N;i++) id[i]=(id[i>>1]>>1)|((i&1)<<ln-1); get_f(f,e);}char s1[maxn],s2[maxn];int main(){ pre(); scanf("%s%s",s1,s2); n=strlen(s1); for(int i=0;i<n;i++) { if(s1[i]-'0'+s2[i]-'0'==1) e++; else if(s1[i]-'0'+s2[i]-'0'==2) m++; }e>>=1; N=1,ln=0; while(N<=2*m) N<<=1,ln++; g[0]=1ll; g[1]=pw(3ll,(Mod-1)/N); for(int i=2;i<=N;i++) g[i]=g[i-1]*g[1]%Mod; for(int i=0;i<=m;i++) f[i]=sN[i+1]; solve(); ll ans=0; for(int i=0;i<=m;i++) (ans+=f[i]*si[e]%Mod*sN[m-i]%Mod*si[e+i]%Mod*si[m-i]%Mod*si[m-i]%Mod*C(e+m,m-i)%Mod)%=Mod; printf("%lld\n",ans); return 0;}
F
wxh太强辣 http://blog.csdn.net/wxh010910/article/details/77752687
最优策略肯定是哪种剩下的多答哪种,将问题抽象在二维平面上,由(n,m)走到(0,0)
不妨设n>=m,发现当路径与y=x(x>0)不相交时一定是答对n个,
若相交,每次在交点时有1/2的概率得到1的增量,并且除去所有增量这条路径答案仍是n,
于是答案是
code:
#include<set>#include<map>#include<deque>#include<queue>#include<stack>#include<cmath>#include<ctime>#include<bitset>#include<string>#include<vector>#include<cstdio>#include<cstdlib>#include<cstring>#include<climits>#include<complex>#include<iostream>#include<algorithm>#define ll long long#define inf 1e9using namespace std;const ll Mod = 998244353;const int maxn = 1010000;ll pw(ll x,ll k){ ll re=1ll; for(;k;k>>=1,x=x*x%Mod) if(k&1) re=re*x%Mod; return re;}int n,m;ll s[maxn],invs[maxn],inv[maxn];void pre(){ s[0]=1ll; for(ll i=1;i<maxn;i++) s[i]=s[i-1]*i%Mod; invs[maxn-1]=pw(s[maxn-1],Mod-2); for(ll i=maxn-2;i>=0;i--) invs[i]=invs[i+1]*(i+1)%Mod;}ll C(const int i,const int j){return s[i]*invs[j]%Mod*invs[i-j]%Mod;}int main(){ pre(); scanf("%d%d",&n,&m); if(n<m) swap(n,m); ll ans=0; for(int i=1;i<=m;i++) (ans+=C(2*i,i)*C(n-i+m-i,n-i)%Mod)%=Mod; ll inv=pw(C(n+m,m),Mod-2); ans=ans*invs[2]%Mod*inv%Mod; (ans+=n)%=Mod; printf("%lld\n",ans); return 0;}
- AGC 019
- webrtc agc
- AGC说明
- AGC 说明
- AGC 018
- AGC 017
- AGC 016
- AGC 015
- AGC 014
- AGC 013
- AGC 012
- AGC 011
- AGC:D
- AEC、AGC、ANS是什么意思?
- AGC,ANS,AEC
- AEC、AGC、ANS 作用
- AEC、AGC、ANS是什么意思
- AGC算法分析
- Javascript 设计模式 亨元(Flyweight)模式jQuery.single方法代码修正
- JavaWeb的Dao快速开发记忆笔记
- hive安装
- 多线程死锁的产生以及如何避免死锁
- JZOJ3477. 【NOIP2013初赛】青蛙(2017.10B组)
- AGC 019
- Java空字符串与null区别
- C++ Web 编程
- 算法笔记 //02_最大间隙问题(线性时间)
- 基础练习 数列排序
- 032 参数方程确定的函数导数
- ThinkPHP M()函数和D()函数的区别
- EasyUI动态加载button按钮
- My first HTML5 game in Construct 2