cqoi2016
2016-05-23 00:07
288 查看
cqoi2016
不同的最小割做法同zjoi2011最小割,题解略。
#include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<string> #include<cmath> #include<algorithm> #define inf 1050000000 #define N 855 #define M 17005 using namespace std; int n,m,S,T,tot,po ,lx ,rx ,ans ; int k=1,la ,ff[M],q ,dep ,flag ,out[N*N]; struct node{int a,b,c;}map[M]; void add(int a,int b,int c) { map[++k]=(node){a,b,c};ff[k]=la[a];la[a]=k; map[++k]=(node){b,a,c};ff[k]=la;la[b]=k; } int dfs(int x,int flow) { if(x==T)return flow; int res=0,tmp; for(int a=la[x];a&&flow>0;a=ff[a]) if(dep[map[a].b]==dep[x]+1&&map[a].c) { tmp=dfs(map[a].b,min(flow,map[a].c)); map[a].c-=tmp;map[a^1].c+=tmp;res+=tmp;flow-=tmp; } if(res==0)dep[x]=-1; return res; } bool bfs() { memset(dep,0,sizeof(dep)); int l=1,r=2;q[1]=S;dep[S]=1; while(l<r) { int x=q[l];l++; for(int a=la[x];a;a=ff[a]) if(!dep[map[a].b]&&map[a].c) q[r]=map[a].b,dep[q[r]]=dep[x]+1,r++; } return dep[T]; } void dfs(int x) { flag[x]=1; for(int a=la[x];a;a=ff[a]) if(map[a].c&&!flag[map[a].b])dfs(map[a].b); } void solve(int l,int r) { if(l==r)return; int res=0;S=po[l];T=po[r]; for(int i=2;i<=k;i+=2) map[i].c=map[i^1].c=(map[i].c+map[i^1].c>>1); while(bfs())res+=dfs(S,inf); memset(flag,0,sizeof(flag));dfs(S); for(int i=1;i<=n;i++)if(flag[i]) for(int j=1;j<=n;j++)if(!flag[j]) ans[i][j]=ans[j][i]=min(ans[i][j],res); int l1=0,l2=0; for(int i=l;i<=r;i++) { if(flag[po[i]])lx[++l1]=po[i]; else rx[++l2]=po[i]; } for(int i=l,j=1;j<=l1;i++,j++)po[i]=lx[j]; for(int i=l+l1,j=1;j<=l2;i++,j++)po[i]=rx[j]; solve(l,l+l1-1);solve(l+l1,r); } int main() { int a,b,c,x,res; scanf("%d%d",&n,&m); for(int i=1;i<=n;i++)po[i]=i; for(int i=1;i<=m;i++) scanf("%d%d%d",&a,&b,&c),add(a,b,c); memset(ans,127,sizeof(ans)); solve(1,n); for(int i=1;i<=n;i++) for(int j=i+1;j<=n;j++)out[++tot]=ans[i][j]; sort(out+1,out+tot+1); printf("%d\n",unique(out+1,out+tot+1)-out-1); return 0; }
[b]K远点对
裸的kd树维护最远点对。
#include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<string> #include<cmath> #include<queue> #include<algorithm> #define inf 2100000000 #define ll long long #define N 100010 using namespace std; int n,rt,k,D,cnt; struct info{ int c[2]; bool operator<(const info &x)const{ return c[D]<x.c[D]||(c[D]==x.c[D]&&c[D^1]<x.c[D^1]); } }s ; struct node{int lc,rc,minx,maxx,miny,maxy,x,y;}t ; priority_queue<ll>q; class Kevin_Durant_Tree { void update(int x) { int lc=t[x].lc,rc=t[x].rc; t[x].minx=min(t[x].x,min(t[lc].minx,t[rc].minx)); t[x].miny=min(t[x].y,min(t[lc].miny,t[rc].miny)); t[x].maxx=max(t[x].x,max(t[lc].maxx,t[rc].maxx)); t[x].maxy=max(t[x].y,max(t[lc].maxy,t[rc].maxy)); } ll pf(int x){return (ll)x*x;} ll get(int x1,int y1,int x2,int y2) { return pf(x1-x2)+pf(y1-y2); } ll cal(int x,int X,int Y) { if(!x)return 0; ll res=0; res=max(res,get(t[x].minx,t[x].miny,X,Y)); res=max(res,get(t[x].minx,t[x].maxy,X,Y)); res=max(res,get(t[x].maxx,t[x].miny,X,Y)); res=max(res,get(t[x].maxx,t[x].maxy,X,Y)); return res; } public: void build(int &x,int l,int r,int inv) { if(l>r)return;x=++cnt; int mid=l+r>>1; D=inv;nth_element(s+l,s+mid,s+r+1); t[x].minx=t[x].maxx=t[x].x=s[mid].c[0]; t[x].miny=t[x].maxy=t[x].y=s[mid].c[1]; build(t[x].lc,l,mid-1,inv^1); build(t[x].rc,mid+1,r,inv^1); update(x); } void qry(int x,int X,int Y) { if(!x)return; int lc=t[x].lc,rc=t[x].rc; ll ls=cal(lc,X,Y),rs=cal(rc,X,Y); ll tmp=get(t[x].x,t[x].y,X,Y); if(tmp>-q.top())q.pop(),q.push(-tmp); if(ls>rs) { if(ls>-q.top())qry(lc,X,Y); if(rs>-q.top())qry(rc,X,Y); } else { if(rs>-q.top())qry(rc,X,Y); if(ls>-q.top())qry(lc,X,Y); } } void clear() { t[0].minx=t[0].miny=inf; t[0].maxx=t[0].maxy=0; } }T; int main() { scanf("%d%d",&n,&k); for(int i=1;i<=n;i++) scanf("%d%d",&s[i].c[0],&s[i].c[1]); T.clear();T.build(rt,1,n,0); for(int i=1;i<=2*k;i++)q.push(0); for(int i=1;i<=n;i++) T.qry(rt,s[i].c[0],s[i].c[1]); printf("%lld\n",-q.top()); return 0; }
手机号码
裸的数位dp,f[x][A][C][D][E][F]分别表示前x位,上一位为A,连续B个相同,是否满足连续超过3个相同,是否有4,是否有8,是否等于上界。
写成记忆化搜索代码会好写很多。
#include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<string> #include<cmath> #include<algorithm> #define ll long long #define N 13 using namespace std; int flag [4][2][2][2][2],f [4][2][2][2][2],p ;ll l,r,s ; int dfs(int x,int A,int B,int C,int D,int E,ll num) { if((num>s[x+1])||(D&&E)||(x<0&&!C))return 0; if(x<0)return 1; int F=(num==s[x+1]); if(flag[x][A][B][C][D][E][F])return f[x][A][B][C][D][E][F]; flag[x][A][B][C][D][E][F]=1;ll tmp=0; for(int i=0;i<=9;i++) { if(i==A)tmp+=dfs(x-1,i,min(B+1,3),C|(B>=2),D|(i==4),E|(i==8),num*10+i); else tmp+=dfs(x-1,i,1,C,D|(i==4),E|(i==8),num*10+i); } return f[x][A][B][C][D][E][F]=tmp; } ll work(ll x) { ll res=0,t=x; memset(f,0,sizeof(f)); memset(flag,0,sizeof(flag)); for(int i=0;i<=10;i++)p[i]=t%10,t/=10; for(int i=10;i>=0;i--)s[i]=s[i+1]*10+p[i]; for(int i=1;i<=9;i++) res+=dfs(9,i,1,0,i==4,i==8,i); return res; } int main() { scanf("%lld%lld",&l,&r); printf("%lld\n",work(r)-work(l-1)); return 0; }
[b]密钥破解
模拟+泼辣肉。
#include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<string> #include<cmath> #include<algorithm> #define ll unsigned long long using namespace std; ll e,N,c,n,d,p,q,r,x,y,num; ll add(ll a,ll b,ll mod) {return (a+=b)>=mod?a-mod:a;} ll mul(ll a,ll b,ll n) { ll res=0;a%=n;b%=n; while(b) { if(b&1)res=add(res,a,n); a=(a<<1)%n;b=b>>1; } return res; } ll Pow(ll a,ll b,ll mod) { ll res=1; while(b) { if(b&1)res=mul(res,a,mod); a=mul(a,a,mod);b>>=1; } return res; } ll gcd(ll a,ll b) { if(!b)return a; return gcd(b,a%b); } void exgcd(ll a,ll b) { if(b==0){x=1;y=0;return;} exgcd(b,a%b);ll t=x;x=y;y=t-a/b*y; } ll Abs(ll x){return x>0?x:-x;} ll Pollard_rho(ll n,ll c) { ll i=1,k=2,x,y,d,p; x=rand()%(n-1)+1;y=x; while(1) { i++;x=add(mul(x,x,n),c,n); if(y==x)return n; p=Abs(x-y);d=gcd(p,n); if(d!=1&&d!=n)return d; if(i==k)y=x,k+=k; } } int main() { srand(666072); scanf("%lld%lld%lld",&e,&N,&c); if(N<=1000000)num=072; else num=666; p=Pollard_rho(N,num); q=N/p;r=(p-1)*(q-1); exgcd(e,r);d=(x+r)%r; n=Pow(c,d,N); printf("%lld% lld\n",d,n); return 0; }
路由表
语文题。建chuai树,每次查询等价于维护一段时间递增序列。
#include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<string> #include<cmath> #include<algorithm> #define N 1000010 using namespace std; int n,cnt,tot,ch [2],pos ,q ,str[50]; char s[20]; class chuai { public: int cal(int top,int l) { int res=0; for(int i=1;i<=top;i++)res+=(q[i]>=l); return res; } void insert(int *s,int len,int ti) { int x=0; for(int i=1;i<=len;i++) { if(!ch[x][s[i]])ch[x][s[i]]=++cnt; x=ch[x][s[i]]; } pos[x]=ti; } int qry(int *s,int l,int r,int len) { int x=0,top=0; for(int i=1;i<=len;i++) { x=ch[x][s[i]]; if(!x)return cal(top,l); if(pos[x]&&pos[x]<=r) { while(q[top]>pos[x]&&top)top--; q[++top]=pos[x]; } } return cal(top,l); } }T; int main() { char ch,cyc,wbs,lxe,yp; int l,r,num,len,A,B,C,D; scanf("%d",&n); while(n--) { scanf(" %c%d %c%d %c%d %c%d",&ch,&A,&wbs,&B,&cyc,&C,&lxe,&D); if(ch=='A') { scanf(" %c%d",&yp,&len); num=A;num=num*256+B; num=num*256+C;num=num*256+D; for(int i=1,j=31;i<=len;i++,j--)str[i]=((num>>j)&1); T.insert(str,len,++tot); } else { scanf("%d%d",&l,&r); len=32;num=A;num=num*256+B; num=num*256+C;num=num*256+D; for(int i=1,j=31;i<=len;i++,j--)str[i]=((num>>j)&1); printf("%d\n",T.qry(str,l,r,len)); } } return 0; }
伪光滑数
终于有一道有点意思的题目。
考虑只要求最大,建立dp,f[i][j]表示前i小额质数选j个的最大值。
维护一下前缀和即可。
f[i][j]=g[i-1][j-k]*num;
g[i][j]=g[i-1][j]+f[i][j];
要求K大,就把每个状态改成一个堆,再把所有状态套进一个大堆。
跑K次,每次取出一个节点换次大。
乘法等价于在堆上打标机,加法等价于合并两个堆。
拿可持久化可并队维护即可。
感觉这种堆套堆得方法还是很经典的。
cyc大爷的做法,二分答案暴搜,直接A了(%%%)。
lxe大爷的做法,对于每个状态维护每个质数使用的个数,然后对于每个状态只对最后两个数字进行转移。也A了(%%%)。lxe大爷似乎用奇怪的办法拆解了我的这个dp,然后码量少了不少。
#include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<string> #include<cmath> #include<queue> #include<algorithm> #define ll long long #define N 18000000 #define MAX 127 using namespace std; int k,D,cnt=1,f[MAX][65],g[MAX][65]; int tot,check[MAX],prime[MAX];ll n; struct node{int lc,rc,dis;ll num,tag;}t ; struct info{ int x,y;ll num; bool operator<(const info &p) const{return num<p.num;} }; priority_queue<info>q; class heap { void pushdown(int x) { if(t[x].tag==1)return; int lc=t[x].lc,rc=t[x].rc; if(lc) { t[++cnt]=t[lc];t[x].lc=cnt; t[cnt].num*=t[x].tag; t[cnt].tag*=t[x].tag; } if(rc) { t[++cnt]=t[rc];t[x].rc=cnt; t[cnt].num*=t[x].tag; t[cnt].tag*=t[x].tag; } t[x].tag=1; } public: int merge(int a,int b) { if(!a)return b;if(!b)return a; if(t[a].num<t[b].num)swap(a,b); int x=++cnt;t[x]=t[a];pushdown(x); t[x].rc=merge(t[x].rc,b); if(t[t[x].lc].dis<t[t[x].rc].dis) swap(t[x].lc,t[x].rc); t[x].dis=t[t[x].rc].dis+1; return x; } int mul(int x,ll y) { t[++cnt]=t[x];t[cnt].tag*=y;t[cnt].num*=y; return cnt; } int add(int a,int b){return merge(a,b);} int erase(int x) { pushdown(x); return merge(t[x].lc,t[x].rc); } }T; int main() { scanf("%lld%d",&n,&k);D=log2(n)+1; for(int i=2;i<=MAX;i++) { if(check[i])continue;prime[++tot]=i; for(int j=i;j<=MAX;j+=i)check[j]=1; } for(int i=0;i<=D;i++)f[0][i]=g[0][i]=1; t[1].num=t[1].tag=t[1].dis=1; for(int i=1;i<=tot;i++) { ll ss=1;g[i][0]=g[i-1][0]; for(int j=1;;j++) { ss*=prime[i]; if(ss<=0||ss>n)break; ll num=1; for(int k=1;k<=j;k++) { num*=prime[i]; f[i][j]=T.add(f[i][j],T.mul(g[i-1][j-k],num)); } q.push((info){i,j,t[f[i][j]].num}); g[i][j]=T.add(g[i-1][j],f[i][j]); } } ll pre=0; for(int i=1;i<k;i++) { info x=q.top();q.pop(); if(x.num==pre)i--;pre=x.num; f[x.x][x.y]=T.erase(f[x.x][x.y]); q.push((info){x.x,x.y,t[f[x.x][x.y]].num}); } printf("%lld\n",q.top().num); return 0; }
相关文章推荐
- ActionBar 用法
- 字父类中,成员特点体现
- SQL注入测试平台 SQLol -2.SELECT注入测试
- Codeforces Round #349 (Div. 1) B. World Tour 最短路+暴力枚举
- 用广播加回调函数可以实现数据的立即加载
- hihoCoder 1298 欧拉函数
- Java Web项目报错The superclass "javax.servlet.http.HttpServlet" was not found on the Java Build Path
- 终于把小说都看完了
- 浏览器的本地存储方法
- JSONP跨域原理和jQuery.getJSON用法
- 百度相册彻底关闭下线
- JSP实现用户登录、注册和退出功能
- JavaScript 中的正则表达式(推荐)
- JavaScript正则表达式上之基本语法(推荐)
- JavaScript正则表达式下之相关方法
- 解决Visual Studio 2012 Update 4 RC启动调试失败的方案
- 细说SQL Server中的视图
- Spring配置详解
- 简单几步 实现vs2010对html5的支持
- php使用ffmpeg向视频中添加文字字幕的实现方法