bzoj1000~1025
以后还是这样 25道题一起发 看着爽
noip失利之后发粪涂墙 刷了一波bzoj
题解:
bzoj1000 A+B问题
这题不同的人有不同的写法,我写了个线段树套Treap,应该还是挺简单的
但是看别的大神的代码跑的飞快就粘过来吧 这题竟然不用树套树,太强了
- #include<iostream>
- #include<cstdio>
- #include<cstdlib>
- #include<cmath>
- #include<cstring>
- #include<algorithm>
- using namespace std;
- int main()
- {
- int a,b;
- cin>>a>>b;
- cout<<a+b;
- return ;
- }
bzoj1001 狼抓兔子
平面图最小割
建图方式比较奇怪,注意一下就可以了
- #include<iostream>
- #include<cstring>
- #include<cstdio>
- using namespace std;
- int n,m;
- int ne;
- struct data{int to,next,v;}e[];
- int head[];
- int h[],q[],ans;
- void insert(int u,int v,int w)
- {
- ne++;
- e[ne].to=v;
- e[ne].v=w;
- e[ne].next=head[u];
- head[u]=ne;
- }
- bool bfs()
- {
- int now,i;
- memset(h,-,sizeof(h));
- int t=,w=;
- q[t]=;h[]=;
- while(t<w)
- {
- now=q[t];t++;
- i=head[now];
- while(i)
- {
- if(e[i].v&&h[e[i].to]<)
- {
- q[w++]=e[i].to;
- h[e[i].to]=h[now]+;
- }
- i=e[i].next;
- }
- }
- if(h[n*m]==-)return ;
- return ;
- }
- int dfs(int x,int f)
- {
- if(x==n*m)return f;
- int i=head[x];
- int w,used=;
- while(i)
- {
- if(e[i].v&&h[e[i].to]==h[x]+)
- {
- w=f-used;
- w=dfs(e[i].to,min(w,e[i].v));
- e[i].v-=w;
- e[i+].v+=w;
- used+=w;
- if(used==f)return f;
- }
- i=e[i].next;
- }
- if(!used)h[x]=-;
- return used;
- }
- void dinic()
- {
- while(bfs())ans+=dfs(,0x7fffffff);
- }
- int main()
- {
- scanf("%d%d",&n,&m);
- int x;
- for(int i=;i<=n;i++)
- for(int j=;j<m;j++)
- {
- scanf("%d",&x);
- insert(m*(i-)+j,m*(i-)+j+,x);
- insert(m*(i-)+j+,m*(i-)+j,x);
- }
- for(int i=;i<n;i++)
- for(int j=;j<=m;j++)
- {
- scanf("%d",&x);
- insert(m*(i-)+j,m*(i)+j,x);
- insert(m*(i)+j,m*(i-)+j,x);
- }
- for(int i=;i<n;i++)
- for(int j=;j<m;j++)
- {
- scanf("%d",&x);
- insert(m*(i-)+j,m*(i)+j+,x);
- insert(m*(i)+j+,m*(i-)+j,x);
- }
- dinic();
- printf("%d",ans);
- return ;
- }
网络流
- #include<iostream>
- #include<cstdio>
- #include<algorithm>
- #include<cmath>
- #include<cstring>
- #include<cstdlib>
- #include<set>
- #include<map>
- #include<vector>
- #include<stack>
- #include<queue>
- #define ll long long
- #define inf 2147383611
- #define MAXN 1001001
- #define MOD
- using namespace std;
- inline int read()
- {
- int x=,f=;
- char ch;ch=getchar();
- while(!isdigit(ch)) {if(ch=='-') f=-;ch=getchar();}
- while(isdigit(ch)) {x=x*+ch-'';ch=getchar();}
- return x*f;
- }
- int n,m,x,ans,lim;
- int to[MAXN*+],val[MAXN*+],first[MAXN*],next[MAXN*+],cnt;
- int dis[MAXN*];
- bool vis[MAXN*];
- void add(int u,int v,int d) {next[++cnt]=first[u],first[u]=cnt,val[cnt]=d,to[cnt]=v;}
- void spfa()
- {
- memset(dis,,sizeof(dis));
- queue <int> q;
- q.push();dis[]=,vis[]=;
- while(!q.empty())
- {
- int k=q.front();
- q.pop();
- vis[k]=;
- for(int i=first[k];i;i=next[i])
- if(dis[to[i]]>dis[k]+val[i])
- {
- dis[to[i]]=dis[k]+val[i];
- if(!vis[to[i]]) {q.push(to[i]);vis[to[i]]=;}
- }
- }
- printf("%d",dis[lim+]);
- }
- int main()
- {
- n=read(),m=read();
- ans=inf,lim=*(m-)*(n-);
- if(n==)
- {
- for(int i=;i<m;i++) {x=read(),ans=min(ans,x);}
- printf("%d",ans);return ;
- }
- if(m==)
- {
- for(int i=;i<n;i++) {x=read(),ans=min(ans,x);}
- printf("%d",ans);return ;
- }
- for(int i=;i<=n;i++)
- {
- for(int j=;j<m;j++)
- {
- x=read();
- if(i==) {add(lim+,j*,x);add(j*,lim+,x);continue;}
- if(i==n) {add(,(n-)*(m-)*+j*-,x);add((n-)*(m-)*+j*-,,x);continue;}
- add((i-)*(m-)*+j*,(i-)*(m-)*+j*-,x);add((i-)*(m-)*+j*-,(i-)*(m-)*+j*,x);
- }
- }
- for(int i=;i<n;i++)
- {
- for(int j=;j<=m;j++)
- {
- x=read();
- if(j==) {add(,(m-)*(i-)*+,x);add(*(m-)*(i-)+,,x);continue;}
- if(j==m) {add(lim+,i*(m-)*,x);add(i*(m-)*,lim+,x);continue;}
- add((i-)*(m-)*+*(j-),(i-)*(m-)*+*j-,x);add((i-)*(m-)*+*j-,(i-)*(m-)*+*(j-),x);
- }
- }
- for(int i=;i<n;i++)
- {
- for(int j=;j<m;j++)
- {
- x=read();
- add((i-)*(m-)*+*j,(i-)*(m-)*+*j-,x);add((i-)*(m-)*+*j-,(i-)*(m-)*+*j,x);
- }
- }
- spfa();
- }
对偶图
bzoj1002 轮状病毒
这题当年应该没多少人严格论证并写出来正解,时至今日已成为一道高精度练习题
网上严格论证。。。稀如凤毛麟角
找规律+高精度
- #include<iostream>
- #include<cstdio>
- using namespace std;
- struct data{
- int a[],len;
- };
- int n;
- data mul(data a,int k)
- {
- for(int i=;i<=a.len;i++)
- a.a[i]*=k;
- for(int i=;i<=a.len;i++)
- {
- a.a[i+]+=a.a[i]/;
- a.a[i]%=;
- }
- if(a.a[a.len+]!=)a.len++;
- return a;
- }
- data sub(data a,data b)
- {
- a.a[]+=;
- int j=;
- while(a.a[j]>=){a.a[j]%=;a.a[j+]++;j++;}
- for(int i=;i<=a.len;i++)
- {
- a.a[i]-=b.a[i];
- if(a.a[i]<){a.a[i]+=;a.a[i+]--;}
- }
- while(a.a[a.len]==)a.len--;
- return a;
- }
- int main()
- {
- data f[];f[].a[]=;f[].a[]=;
- f[].len=f[].len=;
- scanf("%d",&n);
- for(int i=;i<=n;i++)
- f[i]=sub(mul(f[i-],),f[i-]);
- for(int i=f[n].len;i>;i--)
- printf("%d",f[n].a[i]);
- return ;
- }
bzoj1003 物流运输
spfa+dp,dp[i][j]表示从第i天到第j天表示从第i天到第j天都能走的1~n最短路长度
f[i]表示前i天最小费用,初始化f[i]=dp[1][i]
递推式为f[i]=min{f[j]+dp[j+1][i]+k}(i>=2,j∈[1,i-1])
bzoj1004 Cards
置换群 Burnside定理 背包
反正就是个狂拽酷炫吊炸天的背包
具体可以看https://www.cnblogs.com/JoeFan/p/4299628.html这篇文章讲的挺好的
心疼当年考的小伙伴
- #include <cstdio>
- #include <cstring>
- #include <iostream>
- #include <algorithm>
- #define N 110
- using namespace std;
- typedef long long ll;
- int sr,sb,sg,n,m,mod;
- int cir[N][N],v[N],size[N];
- ll f[N][N][N],ans;
- int calc(int x)
- {
- int cnt=;
- memset(v,,sizeof(v));
- memset(size,,sizeof(size));
- for(int i=;i<=n;i++)
- {
- if(v[i])continue;
- int p=cir[x][i];
- cnt++;
- while(!v[p])v[p]=,size[cnt]++,p=cir[x][p];
- }
- memset(f,,sizeof(f));
- f[][][]=;
- for(int i=;i<=cnt;i++)
- for(int j=sr;j>=;j--)
- for(int k=sb;k>=;k--)
- for(int l=sg;l>=;l--)
- {
- if(j>=size[i])f[j][k][l]=(f[j][k][l]+f[j-size[i]][k][l])%mod;
- if(k>=size[i])f[j][k][l]=(f[j][k][l]+f[j][k-size[i]][l])%mod;
- if(l>=size[i])f[j][k][l]=(f[j][k][l]+f[j][k][l-size[i]])%mod;
- }
- return f[sr][sb][sg];
- }
- ll quick_my(ll x,int y)
- {
- ll ret=;
- while(y)
- {
- if(y&)ret=(ret*x)%mod;
- x=(x*x)%mod;
- y>>=;
- }
- return ret;
- }
- int main()
- {
- scanf("%d%d%d%d%d",&sr,&sb,&sg,&m,&mod);
- n=sr+sb+sg;
- for(int i=;i<=m;i++)
- for(int j=;j<=n;j++)
- scanf("%d",&cir[i][j]);
- m++;
- for(int i=;i<=n;i++)cir[m][i]=i;
- ll ans=;
- for(int i=;i<=m;i++)ans=(ans+calc(i))%mod;
- ans=(ans*quick_my(m,mod-))%mod;
- printf("%lld\n",ans);
- }
bzoj1005 明明的烦恼
又是一道结论题
- #include <cstdio>
- #include <cmath>
- #include <cstring>
- struct bignum {
- int l, a[];
- bignum (int t) {
- l = ; memset(a, , sizeof());
- while (t != ) {
- a[++l] = t % ;
- t /= ;
- }
- if (l == ) l = ;
- }
- void mul(int k) {
- for (int i = ; i <= l; i++)
- a[i] *= k;
- for (int i = ; i <= l; i++)
- if (a[i] >= ) {
- int t = i;
- do {
- a[t + ] += a[t] / ;
- a[t++] %= ;
- } while (a[t] >= );
- }
- while (a[l + ] > ) l++;
- }
- void print() {
- printf("%d", a[l]);
- for (int i = l - ; i >= ; i--)
- printf("%04d", a[i]);
- printf("\n");
- }
- };
- int n, m = , tot = , d[], prime[], cnt[];
- bool judge(int k) {
- for (int i = ; i <= sqrt(k); i++)
- if (k % i == ) return false;
- return true;
- }
- void makelist(int n) {
- prime[] = ;
- for (int i = ; i <= n; i++)
- if (judge(i)) prime[++prime[]] = i;
- }
- void compute(int k, int t) {
- for (int i = ; i <= prime[] && prime[i] <= k; i++) {
- int x = , n = k, p = prime[i];
- while (n != ) {
- x += n / p;
- n /= p;
- }
- cnt[i] += x * t;
- }
- }
- int main() {
- //freopen("input.txt", "r", stdin);
- //freopen("output.txt", "w", stdout);
- scanf("%d", &n);
- for (int i = ; i <= n; i++) {
- scanf("%d", &d[i]);
- if (d[i] == -) m++;
- else tot += d[i] - ;
- }
- makelist(n);
- memset(cnt, , sizeof(cnt));
- compute(n - , );
- compute(n - - tot, -);
- for (int i = ; i <= n; i++)
- if (d[i] != -) compute(d[i] - , -);
- bignum ans = ;
- for (int i = ; i <= prime[]; i++)
- for (int j = ; j <= cnt[i]; j++)
- ans.mul(prime[i]);
- for (int i = ; i <= n - - tot; i++)
- ans.mul(m);
- ans.print();
- return ;
- }
代码
prufer序列的相关知识可以见https://www.cnblogs.com/CSU3901130321/p/4898261.html这篇博客
bzoj1006 神奇的国度
简单弦图的染色
可以见CDQ的论文
- #include<iostream>
- #include<cstdio>
- #include<cstdlib>
- #include<algorithm>
- #include<cstring>
- #define inf 0x7fffffff
- #define ll long long
- using namespace std;
- inline ll read()
- {
- ll x=,f=;char ch=getchar();
- while(ch>''||ch<''){if(ch=='-')f=-;ch=getchar();}
- while(ch>=''&&ch<=''){x=x*+ch-'';ch=getchar();}
- return x*f;
- }
- int n,m,cnt,ans;
- int head[],d[],q[],col[],hash[];
- bool vis[];
- struct data{int to,next;}e[];
- void ins(int u,int v)
- {e[++cnt].to=v;e[cnt].next=head[u];head[u]=cnt;}
- int main()
- {
- n=read();m=read();
- for(int i=;i<=m;i++)
- {
- int u=read(),v=read();
- ins(u,v);ins(v,u);
- }
- for(int i=n;i;i--)
- {
- int t=;
- for(int j=;j<=n;j++)
- {
- if(!vis[j]&&d[j]>=d[t])t=j;
- }
- vis[t]=;q[i]=t;
- for(int j=head[t];j;j=e[j].next)
- d[e[j].to]++;
- }
- for(int i=n;i>;i--)
- {
- int t=q[i];
- for(int j=head[t];j;j=e[j].next)hash[col[e[j].to]]=i;
- int j;
- for(j=;;j++)if(hash[j]!=i)break;
- col[t]=j;
- if(j>ans)ans=j;
- }
- printf("%d",ans);
- return ;
- }
bzoj1007 水平可见直线
终于不是结论题了
水题 离散化 单调栈 完事
- #include<iostream>
- #include<cstdio>
- #include<algorithm>
- #include<cstdlib>
- #include<cmath>
- #include<cstring>
- using namespace std;
- const double eps=1e-;
- struct Vec{double a,b;int rank;}lines[];
- Vec st[];int top;
- bool cmp1(Vec x,Vec y)
- {
- if(fabs(x.a-y.a)<eps)return x.b<y.b;
- return x.a<y.a;
- }
- int check[];
- double Sv(Vec a,Vec b){return (b.b-a.b)/(a.a-b.a);}
- void Push(Vec a)
- {
- while(top)
- {
- if(fabs(st[top].a-a.a)<eps)--top;
- else if(top> && Sv(a,st[top-])<=Sv(st[top],st[top-]))--top;
- else break;
- }
- st[++top]=a;
- }
- int main()
- {
- int n;
- scanf("%d",&n);
- for(int i=;i<=n;i++){scanf("%lf%lf",&lines[i].a,&lines[i].b);lines[i].rank=i;}
- sort(lines+,lines+n+,cmp1);
- for(int i=;i<=n;i++)Push(lines[i]);
- for(int i=;i<=top;i++)check[st[i].rank]=;
- for(int i=;i<=n;i++)if(check[i])cout<<i<<" ";
- return ;
- }
bzoj1008 越狱
数学题 要时刻注意%还是不%,%完了是正的负的
- #include<iostream>
- #include<cstdio>
- #include<cstring>
- #include<cstdlib>
- #define mod 100003
- #define ll long long
- using namespace std;
- ll m,n;
- ll qpow(ll a,ll b)
- {
- ll c=,d=a%mod;
- while (b>)
- {
- if (b&)
- c=(c%mod*d%mod)%mod;
- b>>=;
- d=(d%mod*d%mod)%mod;
- }
- return c;
- }
- int main()
- {
- scanf("%lld%lld",&m,&n);
- long long ans=qpow(m,n);
- ans=ans-m*qpow(m-,n-)%mod;
- if (ans<) ans+=mod;
- printf("%lld",ans);
- return ;
- }
bzoj1009 GT考试
KMP+矩阵乘法加速DP
递推式很好想
设a[k][j]为k位后面加一个字母转移到j的方案数
dp[i][j]=∑dp[i−1][k]∗a[k][j](0<=k<=m−1)
因为是线性的 可以矩阵优化
- #include<iostream>
- #include<cstdio>
- #include<algorithm>
- #include<cstdlib>
- #include<cmath>
- #include<cstring>
- #define ll long long
- int m,mod;
- using namespace std;
- struct mat
- {
- ll a[][];
- mat operator*(const mat &y)const
- {
- mat res;
- memset(res.a,,sizeof(res.a));
- for(int i=;i<m;i++)
- for(int j=;j<m;j++)
- for(int k=;k<m;k++)
- {
- res.a[i][j]+=a[i][k]*y.a[k][j];
- res.a[i][j]%=mod;
- }
- return res;
- }
- }a,b;
- mat ksm(mat A,int n)
- {
- mat res;
- if(n==) return A;
- res=ksm(A,n/);
- res=res*res;
- if(n%==)res=res*A;
- return res;
- }
- void mul(int a[][],int b[][],int ans[][])
- {
- int tmp[][];
- for(int i=;i<m;i++)
- for(int j=;j<m;j++)
- {
- tmp[i][j]=;
- for(int k=;k<m;k++)
- tmp[i][j]=(tmp[i][j]+a[i][k]*b[k][j])%mod;
- }
- for(int i=;i<m;i++)
- for(int j=;j<m;j++)
- ans[i][j]=tmp[i][j];
- }
- int sum;
- char ch[];
- int nxt[];
- int main()
- {
- int n;
- scanf("%d%d%d",&n,&m,&mod);
- scanf("%s",ch+);
- int j=;
- for(int i=;i<=m;i++)
- {
- for(;j> && ch[j+]!=ch[i];j=nxt[j]);
- if(ch[j+]==ch[i])j++;
- nxt[i]=j;
- }
- for(int i=;i<m;i++)
- for(int j=;j<=;j++)
- {
- int t=i;
- for(;t>&&ch[t+]-''!=j;t=nxt[t]);
- if(ch[t+]-''==j)t++;
- if(t!=m)b.a[t][i]=(b.a[t][i]+)%mod;
- }
- for(int i=;i<m;i++)a.a[i][i]=;
- while(n)
- {
- if(n&)a=a*b;
- b=b*b;
- n>>=;
- }
- for(int i=;i<m;i++)(sum+=a.a[i][])%=mod;
- printf("%d",sum);
- return ;
- }
bzoj1010 玩具装箱toy
斜率优化
dp[i]=min(dp[j]+(sum[i]-sum[j]+i-j-1-L)^2) (j<i)
推一推 搞成令f[i]=sum[i]+i,c=1+l
然后用一个单调队列维护下凸壳就好了
- #include<cstdio>
- #include<cstring>
- #include<cmath>
- #include<iostream>
- #include<algorithm>
- #include<cstdlib>
- #define ll long long
- using namespace std;
- int n,L,l,r;
- int c[],q[];
- ll s[],f[];
- double slop(int j,int k){return (f[k]-f[j]+(s[k]+L)*(s[k]+L)-(s[j]+L)*(s[j]+L))/(2.0*(s[k]-s[j]));}
- int main()
- {
- scanf("%d%d",&n,&L);L++;
- for(int i=;i<=n;i++)scanf("%d",&c[i]);
- for(int i=;i<=n;i++)s[i]=s[i-]+c[i];
- for(int i=;i<=n;i++)s[i]+=i;
- l=;r=;q[++r]=;
- for(int i=;i<=n;i++)
- {
- while(l<r && slop(q[l],q[l+])<=s[i])l++;
- int t=q[l];
- f[i]=f[t]+(s[i]-s[t]-L)*(s[i]-s[t]-L);
- while(l<r && slop(q[r],i)<slop(q[r-],q[r]))r--;
- q[++r]=i;
- }
- printf("%lld\n",f[n]);
- return ;
- }
bzoj1011 遥远的行星
puts("-nan");
果然HNaNOI
正经做也是可以的
由于“误差不超过5%”
当数据小于50时,暴力 大于50时,用到一些估算技巧
没有做过这么奇怪的题呢
- #include <bits/stdc++.h>
- using namespace std;
- double m[], sum[];
- int main()
- {
- int n;
- double a, ans;
- scanf("%d%lf", &n, &a);
- for(int j = ; j <= n; ++j)
- {
- int i = (int)(a * j + 1e-);
- scanf("%lf", m + j);
- ans = ;
- if(j <= )
- for(int k = ; k <= i; ++k)
- ans += m[k] * m[j] / (j - k);
- else
- ans = sum[i] * m[j] / (j - i / );
- printf("%f\n", ans);
- sum[j] = sum[j - ] + m[j];
- }
- return ;
- }
bzoj1012 最大数
单调队列,二分查找
但其实单调栈也是可以的。。。
看到网上一片线段树的时候我以为我做错了
- #include<cstdio>
- #include<cstdlib>
- #include<cmath>
- #include<cstring>
- #include<algorithm>
- using namespace std;
- int n,m,last,mod;
- int q[],id[],head,tail;
- void add(int x)
- {
- while (q[tail]<=x && tail) tail--;
- q[++tail]=x;id[tail]=++n;
- }
- int query(int x)
- {
- int l=n-x+;
- int k=lower_bound(id+head,id+tail+,l)-id;
- return q[k];
- }
- int main()
- {
- scanf("%d%d",&m,&mod);
- char ch[];
- int x;
- head=;tail=;
- while(m--)
- {
- scanf("%s%d",ch,&x);
- if(ch[]=='A') add((x+last)%mod);
- else printf("%d\n",last=query(x));
- }
- return ;
- }
bzoj1013 Sphere(名字太长辣)
高斯消元法裸题
但是推方程组用了我3张纸
- #include<cstdio>
- #include<algorithm>
- #include<cstring>
- #include<iostream>
- #include<cmath>
- using namespace std;
- #define zero 1e-6
- int n;
- double ans[],a[][],d[][];
- void init() {
- cin>>n;
- for (int i=; i<=n+; i++)
- for (int j=; j<=n; j++) cin>>d[i][j];
- for (int i=; i<=n; i++) {
- for (int j=; j<=n; j++)
- a[i][j] = * (d[i+][j]-d[i][j]),
- a[i][n+] += d[i+][j] * d[i+][j] - d[i][j] * d[i][j];
- }
- memset(ans,,sizeof ans);
- }
- void gauss() {
- for (int i=; i<n; i++) {
- if (fabs(a[i][i])<zero)
- for (int j=i+; j<=n; j++)
- if (abs(a[j][i])>zero) {
- for (int k=; k<=n+; k++) swap(a[i][k],a[j][k]);
- break;
- }
- for (int j=i+; j<=n; j++) {
- double x = a[j][i] / a[i][i];
- for (int k=i; k<=n+; k++) a[j][k] -= a[i][k] * x;
- }
- }
- ans[n]=a[n][n+]/a[n][n];
- for (int i=n-; i; i--) {
- for (int j=i+; j<=n; j++) a[i][n+] -= ans[j]*a[i][j];
- ans[i] = a[i][n+] / a[i][i];
- }
- }
- void print() {
- for (int i=; i<n; i++) printf("%.3lf ",ans[i]);
- printf("%.3lf\n",ans[n]);
- }
- int main() {
- init();
- gauss();
- print();
- return ;
- }
bzoj1014 火星人
Splay,我写了题解
传送门:http://www.cnblogs.com/Kong-Ruo/p/7895957.html
bzoj1015 星球大战
并查集,操作离线
不得不说脑洞挺大的
将操作倒过来
- #include<iostream>
- #include<cstdio>
- #include<cstring>
- #include<algorithm>
- using namespace std;
- int fa[];
- inline int read()
- {
- int x=;char ch=getchar();
- while(ch<''||ch>''){ch=getchar();}
- while(ch>=''&&ch<=''){x=x*+ch-'';ch=getchar();}
- return x;
- }
- int n,m;
- int u,v,atk[],d[],ans[],vis[];
- inline int find(int x){return x==fa[x]?x:fa[x]=find(fa[x]);}
- int first[],to[],next[],cnt=;
- void add(int u,int v){to[++cnt]=v;next[cnt]=first[u];first[u]=cnt;}
- int tmp;
- void destroy(int x)
- {
- int p=find(x),q;
- for(int i=first[x];i;i=next[i])
- {
- if(!vis[to[i]])continue;
- q=find(to[i]);
- if(p!=q){fa[q]=p;tmp--;}
- }
- }
- int main()
- {
- n=read();m=read();
- for(int i=;i<n;i++)fa[i]=i;
- for(int i=;i<=m;i++){u=read(),v=read();add(u,v);add(v,u);}
- int k=read();
- for(int i=;i<=k;i++){atk[i]=read();d[atk[i]]=;}
- for(int i=;i<n;i++)
- {
- if(!d[i])
- {
- tmp++;
- destroy(i);
- vis[i]=;
- }
- }
- ans[k+]=tmp;
- for(int i=k;i>;i--)
- {
- tmp++;
- destroy(atk[i]);
- vis[atk[i]]=;
- ans[i]=tmp;
- }
- for(int i=;i<=k+;i++)printf("%d\n",ans[i]);
- return ;
- }
bzoj1016 最小生成树计数
Kruskal+乘法原理
另:千万不要一看到并查集就写路径压缩!!!
- #include<iostream>
- #include<cstdio>
- #include<cstring>
- #include<algorithm>
- using namespace std;
- const int mod=;
- int fa[];
- struct edge{int x,y,v;}e[];
- struct EDG{int l,r,v;}a[];
- inline int read()
- {
- int x=;char ch=getchar();
- while(ch<''||ch>''){ch=getchar();}
- while(ch>=''&&ch<=''){x=x*+ch-'';ch=getchar();}
- return x;
- }
- int n,m,cnt,cntt,ans,sum;
- bool cmp(edge a,edge b){return a.v<b.v;}
- inline int find(int x){return x==fa[x]?x:find(fa[x]);} //这里不能路径压缩!!!WA了好几遍
- void kruskal()
- {
- sort(e+,e+m+,cmp);
- for(int i=;i<=m;i++)
- {
- if(e[i].v!=e[i-].v){a[++cnt].l=i;a[cnt-].r=i-;}
- int p=find(e[i].x),q=find(e[i].y);
- if(p!=q){fa[p]=q;a[cnt].v++;cntt++;}
- }
- a[cnt].r=m;
- }
- void dfs(int x,int c,int k)
- {
- if(c==a[x].r+)
- {
- if(k==a[x].v)sum++;
- return;
- }
- int p=find(e[c].x),q=find(e[c].y);
- if(p!=q)
- {
- fa[p]=q;
- dfs(x,c+,k+);
- fa[p]=p;fa[q]=q;
- }
- dfs(x,c+,k);
- }
- void kkruskal()
- {
- for(int i=;i<=n;i++)fa[i]=i;
- for(int i=;i<=cnt;i++)
- {
- sum=;
- dfs(i,a[i].l,);
- ans=(ans*sum)%mod;
- for(int j=a[i].l;j<=a[i].r;j++)
- {
- int p=find(e[j].x),q=find(e[j].y);
- if(p!=q)fa[p]=q;
- }
- }
- }
- int main()
- {
- ans++;
- n=read();m=read();
- for(int i=;i<=n;i++)fa[i]=i;
- for(int i=;i<=m;i++)e[i].x=read(),e[i].y=read(),e[i].v=read();
- kruskal();
- if(cntt!=n-){printf("");return ;}
- kkruskal();
- printf("%d",ans);
- return ;
- }
bzoj1017 魔兽地图DotR
斗地主加强版
装备合成形成一个森林
预处理出高级物品的力量,价格,购买上限
用f[i][j][k]表示前i个物品 有j个用于合成 总花费为k时提供的力量最大值
对于以a为根的子树枚举合成b个物品,再把剩下的钱买不用于合成的物品
用ff[i][j]表示以a为根的子树里的前i个节点花费为j时可以获得的力量最大值
再d一遍
- #include<iostream>
- #include<cstdio>
- #include<algorithm>
- #include<cstring>
- #include<cstdlib>
- #include<cmath>
- using namespace std;
- inline int read()
- {
- int x=,f=;
- char ch=getchar();
- while(!isdigit(ch)){if(ch=='-')f=-;ch=getchar();}
- while(isdigit(ch)){x=*x+f-'';ch=getchar();}
- return x*f;
- }
- const int maxn=;
- const int inf=;
- int dp[maxn][maxn*][],c[maxn][maxn*],f[maxn][maxn*];
- int n,m,t;
- int lim[maxn],pri[maxn],p[maxn];
- int rd[maxn];
- struct EDG
- {
- int to,next,val;
- }e[maxn*maxn*];
- int first[maxn],cnt;
- inline void add(int u,int v,int w)
- {
- e[++cnt].to=v;
- e[cnt].next=first[u];
- e[cnt].val=w;
- first[u]=cnt;
- rd[v]++;
- }
- char ch[];
- void dfs(int x)
- {
- if(!first[x])
- {
- lim[x]=min(lim[x],m/pri[x]);
- for(int i=;i<=lim[x];i++)
- for(int j=i;j<=lim[x];j++)
- dp[x][i][j*pri[x]]=(j-i)*p[x];
- return;
- }
- lim[x]=;
- for(int i=first[x];i;i=e[i].next)
- {
- dfs(e[i].to);
- lim[x]=min(lim[x],lim[e[i].to]/e[i].val);
- pri[x]+=e[i].val*pri[e[i].to];
- }
- lim[x]=min(lim[x],m/pri[x]);
- memset(c,-0x3f3f3f3f,sizeof(c));
- c[][]=;
- for(int i=lim[x];i>=;i--)
- {
- int cc=;
- for(int j=first[x];j;j=e[j].next)
- {
- cc++;
- for(int k=;k<=m;k++)
- for(int l=;l<=k;l++)
- c[cc][k]=max(c[cc][k],c[cc-][k-l]+dp[e[j].to][i*e[j].val][l]);
- }
- for(int j=;j<=i;j++)
- for(int k=;k<=m;k++)
- dp[x][j][k]=max(dp[x][j][k],c[cc][k]+p[x]*(i-j));
- }
- }
- int main()
- {
- memset(dp,-0x3f3f3f3f,sizeof(dp));
- scanf("%d%d",&n,&m);
- int x,y,uu;
- for(int i=;i<=n;i++)
- {
- scanf("%d%d",&p[i]);
- scanf("%s",ch);
- if(ch[]=='B')scanf("%d%d",&pri[i],&lim[i]);
- else
- {
- scanf("%d",&x);
- for(int j=;j<=x;j++)
- {
- scanf("%d%d",&y,&uu);
- add(i,y,uu);
- }
- }
- }
- for(int z=;z<=n;z++)
- {
- if(!rd[z])
- {
- dfs(z);
- t++;
- for(int i=;i<=m;i++)
- for(int j=;j<=i;j++)
- for(int k=;k<=lim[z];k++)
- f[t][i]=max(f[t][i],f[t-][j]+dp[z][k][i-j]);
- }
- }
- int ans=-;
- for(int i=;i<=m;i++)ans=max(ans,f[t][i]);
- printf("%d\n",ans);
- }
bzoj1008 堵塞的交通Traffic
本来以为线段树都是慈眉善目的
线段树每个节点记一个2*2矩阵中6组连通性
走的时候左边的节点先走到最左边,右边节点先走到最右边
然后往中间走
- #include<iostream>
- #include<cstdio>
- #include<algorithm>
- #include<cstring>
- #include<cstdlib>
- #define l(x) (x<<1)
- #define r(x) ((x<<1)|1)
- using namespace std;
- const int maxn=;
- char opt[];
- int x1,y1,x2,y2,c;
- struct Segtree
- {
- struct Martix
- {
- int a1[][];
- int a2[];
- };
- struct Treenode
- {
- int l,r;
- Martix s;
- }tr[maxn];
- int bl[maxn][];
- Martix upd(Martix s1,Martix s2,int b[])
- {
- Martix res;
- for(int i=;i<=;i++)
- for(int j=;j<=;j++)
- res.a1[i][j]=s1.a1[i][] && b[] && s2.a1[][j] || s1.a1[i][] && b[] && s2.a1[][j];
- res.a2[]=s1.a2[] || s1.a1[][] && b[] && s2.a2[] && b[] && s1.a1[][];
- res.a2[]=s2.a2[] || s2.a1[][] && b[] && s1.a2[] && b[] && s2.a1[][];
- return res;
- }
- Martix getc(int id,int l,int r)
- {
- int mid=(tr[id].l+tr[id].r)>>;
- if(l<=tr[id].l && r>=tr[id].r) return tr[id].s;
- else if(l>mid)return getc(r(id),l,r);
- else if(r<=mid)return getc(l(id),l,r);
- else return upd(getc(l(id),l,r),getc(r(id),l,r),bl[id]);
- }
- void update(bool f,int id,int sx,int sy,int gx,int gy)
- {
- int mid=(tr[id].l+tr[id].r)>>;
- if(sx==gx && sy==mid)
- {
- bl[id][sx]=f;
- tr[id].s=upd(tr[l(id)].s,tr[r(id)].s,bl[id]);
- }
- else if(tr[id].l==tr[id].r)
- tr[id].s.a1[][]=tr[id].s.a1[][]=tr[id].s.a2[]=tr[id].s.a2[]=f;
- else
- {
- if(gy<=mid)update(f,l(id),sx,sy,gx,gy);
- else update(f,r(id),sx,sy,gx,gy);
- tr[id].s=upd(tr[l(id)].s,tr[r(id)].s,bl[id]);
- }
- }
- void build(int id,int l,int r)
- {
- tr[id].l=l;tr[id].r=r;
- if(l==r)
- {
- tr[id].s.a1[][]=tr[id].s.a1[][]=;
- return;
- }
- int mid=(l+r)>>;
- build(l(id),l,mid);
- build(r(id),mid+,r);
- }
- void query(int sx,int sy,int gx,int gy)
- {
- Martix L=getc(,,sy),Mid=getc(,sy,gy),R=getc(,gy,c);
- int res=;
- for(int i=;i<=;i++)
- for(int j=;j<=;j++)
- if(Mid.a1[i][j]&&(i==sx||L.a2[])&&(j==gx||R.a2[])){res=;break;}
- if(res)printf("Y\n");
- else printf("N\n");
- }
- }seg;
- int main()
- {
- scanf("%d",&c);
- seg.build(,,c);
- while() {
- scanf("%s",opt);
- if(opt[]=='E') break;
- scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
- --x1; --x2;
- if(y1>y2) {
- swap(x1,x2);
- swap(y1,y2);
- }
- if(opt[]=='O') seg.update(,,x1,y1,x2,y2);
- else if(opt[]=='C') seg.update(,,x1,y1,x2,y2);
- else seg.query(x1,y1,x2,y2);
- }
- return ;
- }
bzoj1019 汉诺塔
一个经典的汉诺塔型递推
结合汉诺塔&&BLAH,可想到递推方程: f[x][i] ,g[x][i] 分别表示,当前x柱上有i个圆盘,将它们移至任意另一个柱的操作数,和另一柱子的编号.(如上,这显然对任意连续的i个圆盘,都是唯一固定的)
f[x][i],g[x][i] 可由 f[][i-1],g[][i-1] 推得:
汉诺塔的经典转移,先做子问题把x柱上的i-1个圆盘移走,再把第i个大圆盘移走..
若设y=g[x][i-1],z=1+2+3-y-x(即除x,y以外的柱子编号)
即1) x上i-1个圆盘移至y上
2)由于不能对一个圆盘进行重复操作,所以必是将x上的第i个圆盘,移至z
由于i个圆盘还没叠到一起,所以接下来显然还要再次移动y上的i-1个,这时需要分类讨论:
若 f[y][i-1]=z:
3)移到z后,便结束了
综合以上,这种情况下,f[x][i]=f[x][i-1]+1+f[y][i-1],g[x][i]=z
若f[y][i-1]=x:
3)i-1个圆盘移至x
4)不能对一个圆盘进行重复操作,所以必将z上的第i个圆盘,移至y
5)因g[x][i-1]=y,所以x上i-1个圆盘移至y,结束
综合以上,这种情况下,f[x][i]=f[x][i-1]+1+f[y][i-1]+1+f[x][i-1],g[x][i]=y
- #include<iostream>
- #include<cstdio>
- #include<cstdlib>
- #include<cstring>
- #include<algorithm>
- #include<cmath>
- #define LL long long
- using namespace std;
- int v[],n,g[][];
- LL f[][];
- int main()
- {
- scanf("%d",&n);
- for (int i=;i<=;i++)
- {
- char s[];
- scanf("%s",s);
- int from=s[]-'A'+,to=s[]-'A'+;
- if (v[from]) continue;
- v[from]=;
- g[from][]=to,f[from][]=;
- }
- for (int i=;i<=n;i++)
- for (int j=;j<=;j++)
- {
- int y=g[j][i-];
- int z=-y-j;
- f[j][i]=f[j][i-]+;
- if (z==g[y][i-])
- {
- f[j][i]+=f[y][i-];
- g[j][i]=z;
- }
- else
- {
- f[j][i]+=f[y][i-]++f[j][i-];
- g[j][i]=y;
- }
- }
- cout<<f[][n]<<endl;
- return ;
- }
bzoj1020 安全的航线
看着莫队的论文战战兢兢的做完这道题
计算几何入门题
- #include<iostream>
- #include<cstdio>
- #include<cstdlib>
- #include<cmath>
- #include<cstring>
- #include<algorithm>
- using namespace std;
- const double eps=1e-;
- const int MAXQ=;
- int n,m;double ans;
- int dcmp(double a)
- {
- if(fabs(a)<eps)return ;
- else return a>?:-;
- }
- struct Vector
- {
- double x,y;
- Vector operator +(const Vector &a)const{return (Vector){x+a.x,y+a.y};}
- Vector operator -(const Vector &a)const{return (Vector){x-a.x,y-a.y};}
- bool operator ==(const Vector &a)const{return dcmp(x-a.x)== && dcmp(y-a.y)==;}
- Vector operator *(const double &a)const{return (Vector){x*a,y*a};}
- Vector operator /(const double &a)const{return (Vector){x/a,y/a};}
- void Read(){scanf("%lf %lf",&x,&y);}
- }temp[];
- double dot(Vector a,Vector b){return a.x*b.x+a.y*b.y;}
- double Length(Vector a){return sqrt(dot(a,a));}
- double Angle(Vector a,Vector b){return acos(dot(a,b)/Length(a)/Length(b));}
- double Xmult(Vector a,Vector b){return a.x*b.y-b.x*a.y;}
- double Area(Vector a,Vector b,Vector c){return Xmult(b-a,c-a);}
- int Intersec(Vector a,Vector b,Vector c,Vector d)
- {
- if(max(a.x,b.x)<min(c.x,d.x))return false;
- if(max(a.y,b.y)<min(c.y,d.y))return false;
- if(max(c.x,d.x)<min(a.x,b.x))return false;
- if(max(c.y,d.y)<min(a.y,b.y))return false;
- if(Area(c,b,a)*Area(b,d,a)<)return false;
- if(Area(a,d,c)*Area(d,b,c)<)return false;
- return true;
- }
- Vector Interpoint(Vector a,Vector b,Vector c,Vector d)
- {
- Vector u=a-c;
- double t=Xmult(d,u)/Xmult(b,d);
- return a+b*t;
- }
- Vector Normal(Vector a){return (Vector){-a.y,a.x};}
- double Distoline(Vector p,Vector a,Vector b)
- {
- Vector v1=b-a,v2=p-a;
- return fabs(Xmult(v1,v2)/Length(v1));
- }
- int Onseg(Vector p,Vector a,Vector b){return dcmp(Xmult(a-p,b-p))== && dcmp(dot(a-p,b-p))<;}
- #define point Vector
- struct Seg{point a,b;}que[];
- struct polygon
- {
- point ps[];
- int cnt;
- inline int inpo(point &a)
- {
- int tot=;
- for(int i=;i<=cnt;i++)
- if(Onseg(a,ps[i],ps[i%cnt+]))return ;
- point ray=(point){-,a.y+0.1};
- a.y+=0.1;
- for(int i=;i<=cnt;i++)
- tot+=Intersec(ray,a,ps[i],ps[i%cnt+]);
- a.y-=0.1;
- return tot&;
- }
- }island[];
- struct near
- {
- point p;
- double dis;
- };
- near disps(point a,point b,point c)
- {
- if(b==c)return (near){b,Length(b-a)};
- Vector v1=c-b,v2=a-b,v3=a-c;
- if(dcmp(dot(v1,v2))<=) return (near){b,Length(v2)};
- if(dcmp(dot(v1,v3))>=) return (near){c,Length(v3)};
- Vector v=Normal(b-c);
- point ans=Interpoint(a,v,b,v1);
- return (near){ans,Length(a-ans)};
- }
- bool check(point a)
- {
- for(int i=;i<=n;i++)
- if(island[i].inpo(a))
- return true;
- return false;
- }
- near Find(point &p)
- {
- if(check(p)) return (near){p,};
- near ans1;
- ans1.dis=<<;
- for(int i=;i<=n;i++)
- for(int j=;j<=island[i].cnt;j++)
- {
- near get=disps(p,island[i].ps[j],island[i].ps[j%island[i].cnt+]);
- if(dcmp(ans1.dis-get.dis)>=) ans1=get;
- }
- ans=max(ans,ans1.dis);
- return ans1;
- }
- void dfs()
- {
- int front=,rear=;
- for(int i=;i<m;i++)
- que[++rear]=(Seg){temp[i],temp[i+]},Find(temp[i]);
- Find(temp[m]);
- Seg head;
- while(front!=rear)
- {
- head=que[front=front%MAXQ+];
- point p1=Find(head.a).p,p2=Find(head.b).p,l=head.a,r=head.b,mid=(l+r)/;
- while(Length(r-l)>1e-)
- {
- point mid=(r+l)/;
- if(Length(mid-p1)<Length(mid-p2)) l=mid;
- else r=mid;
- }
- double nowans=max(Length(l-p1),Length(l-p2));
- Find(l);
- if(ans+0.005<nowans) que[rear=rear%MAXQ+]=(Seg){head.a,mid},que[rear=rear%MAXQ+]=(Seg){mid,head.b};
- }
- }
- int main()
- {
- scanf("%d %d",&n,&m);
- for(int i=;i<=m;i++)
- temp[i].Read();
- for(int i=;i<=n;i++)
- {
- scanf("%d",&island[i].cnt);
- for(int j=;j<=island[i].cnt;j++)
- island[i].ps[j].Read();
- }
- dfs();
- printf("%.2lf",ans);
- }
bzoj1021 循环的债务
dp[i][j][k]表示第i种钱,第一个人还有j块钱,第二个人还有k块钱时的交换钞票数
然后依然是个背包
- #include<iostream>
- #include<cstdio>
- #include<algorithm>
- #include<cstring>
- #include<cstdlib>
- #include<cmath>
- using namespace std;
- int x1,x2,x3;
- int cnt[][],sum[];
- const int m[]={,,,,,,};
- int f[][][];
- int g[];
- int tmp[];
- int gcd(int a,int b){return b?gcd(b,a%b):a;}
- int main()
- {
- scanf("%d%d%d",&x1,&x2,&x3);
- for(int i=;i<=;i++)
- for(int j=;j<=;j++)
- {
- scanf("%d",&cnt[i][j]);
- sum[i]=sum[i]+cnt[i][j]*m[j];
- }
- int r1=sum[]-x1+x3,r2=sum[]-x2+x1;
- g[]=;
- for(int i=;i<=;i++)g[i]=gcd(g[i-],m[i]);
- memset(f,0x3f,sizeof(f));
- f[][sum[]][sum[]]=;
- for(int i=;i>=;i--)
- {
- int j=sum[]+sum[]+sum[];
- while((j-r1)%g[i])j--;
- for(;j>=;j-=g[i])
- {
- int k=sum[]+sum[]+sum[]-j;
- while((k-r2)%g[i])k--;
- for(;k>=;k-=g[i])
- {
- if(f[i][j][k]>)continue;
- f[i-][j][k]=min(f[i-][j][k],f[i][j][k]);
- for(int x=;x<=;x++)
- {
- int y=(x+)%,z=(x+)%;
- for(int xx=;xx<=cnt[x][i];xx++)
- for(int yy=;yy<=xx;yy++)
- {
- tmp[x]=-xx*m[i];tmp[y]=yy*m[i];z[tmp]=(xx-yy)*i[m];
- f[i-][j+tmp[]][k+tmp[]]=min(f[i-][j+tmp[]][k+tmp[]],f[i][j][k]+xx);
- }
- //Invisible w
- for(int xx=;xx<=cnt[y][i];xx++)
- for(int yy=;yy<=cnt[z][i];yy++)
- {
- tmp[x]=(xx+yy)*m[i];
- tmp[y]=-xx*m[i];tmp[z]=-yy*m[i];
- f[i-][j+tmp[]][k+tmp[]]=min(f[i-][j+tmp[]][k+tmp[]],f[i][j][k]+xx+yy);
- }
- }
- }
- }
- }
- int ans=f[][r1][r2];
- printf(ans>=?"impossible":"%d",ans);
- return ;
- }
bzoj1022 小约翰的游戏
一看这不是Nim吗然后交了个Nim上去
发现竟然跟Nim是相反的
然后出现了一个新的小细节:如果有偶数堆,每堆一个石子,先手会赢
博弈论的题竟然不是Alice和Bob,好评
- #include<iostream>
- #include<cstdio>
- #include<cstdlib>
- #include<cmath>
- #include<cstring>
- #include<algorithm>
- using namespace std;
- int x,sum,flag;
- int T,n;
- int main()
- {
- scanf("%d",&T);
- while(T--)
- {
- sum=,flag=;
- scanf("%d",&n);
- for(int i=;i<=n;i++)
- {
- scanf("%d",&x);
- sum^=x;
- if(x!=)flag=;
- }
- if((sum== && flag==) || (sum!= && flag==))printf("John\n");
- else printf("Brother\n");
- }
- return ;
- }
bzoj1023 仙人掌图
很大意义上来说这不算仙人掌的题
搞成一棵树找直径
- #include<iostream>
- #include<cstdio>
- #include<cstdlib>
- #include<cmath>
- #include<cstring>
- #include<algorithm>
- using namespace std;
- int first[],to[],next[],fa[],cnt;
- int ind,dfn[],low[],depth[],q[];
- int a[];
- int ans;
- int f[];
- int n,m;
- inline int read()
- {
- int x=,f=;
- char ch=getchar();
- for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-f;
- for(;isdigit(ch);ch=getchar())x=*x+ch-'';
- return x*f;
- }
- inline void add(int u,int v)
- {
- to[++cnt]=v;
- next[cnt]=first[u];
- first[u]=cnt;
- }
- inline void dp(int x,int y)
- {
- int cnt=depth[y]-depth[x]+,head=,tail=,i;
- for (i=y; i!=x; i=fa[i]) a[cnt--]=f[i]; a[]=f[x];
- cnt=depth[y]-depth[x]+; q[]=;
- for (i=; i<=cnt; i++) a[i+cnt]=a[i];
- for (i=; i<=cnt+(cnt>>); i++){
- if (i-q[head]>(cnt>>)) head++;
- ans=max(ans,a[i]+i+a[q[head]]-q[head]);
- while (head<=tail && a[i]-i>=a[q[tail]]-q[tail]) tail--; q[++tail]=i;
- }
- for (i=; i<=cnt; i++) f[x]=max(f[x],a[i]+min(i-,cnt-i+));
- }
- inline void Tarjan_dfs(int x)
- {
- dfn[x]=low[x]=++ind;
- for(int i=first[x];i;i=next[i])
- {
- if(to[i]==fa[x])continue;
- if(!dfn[to[i]])
- {
- fa[to[i]]=x;
- depth[to[i]]=depth[x]+;
- Tarjan_dfs(to[i]);
- }
- low[x]=min(low[x],low[to[i]]);
- if(low[to[i]]>dfn[x])
- {
- ans=max(ans,f[to[i]]+f[x]+);
- f[x]=max(f[x],f[to[i]]+);
- }
- }
- for(int i=first[x];i;i=next[i])
- if(fa[to[i]]!=x && dfn[x]<dfn[to[i]])dp(x,to[i]);
- }
- int main()
- {
- n=read(); m=read(); int i;
- for (i=; i<=m; i++)
- {
- int tmp=read(),last=;
- while (tmp--){
- int x=read(); if (last){ add(x,last); add(last,x); } last=x;
- }
- }
- Tarjan_dfs();
- printf("%d\n",ans);
- return ;
- }
bzoj1024 生日快乐
爆搜,每次把蛋糕砍成两块
- #include <iostream>
- #include <algorithm>
- #include <cstring>
- #include <cstdio>
- #include <cmath>
- using namespace std;
- double s;
- double dfs(double x,double y,int n)
- {
- if(n==)
- {
- return max(x/y,y/x);
- }
- double ans=1e10;
- for(int i=;i<=n/;i++)
- {
- double tx=x*i/n,ty=y*i/n;
- ans=min(ans,max(dfs(tx,y,i),dfs(x-tx,y,n-i)));
- ans=min(ans,max(dfs(x,ty,i),dfs(x,y-ty,n-i)));
- }
- return ans;
- }
- int x,y,n;
- int main()
- {
- scanf("%d%d%d",&x,&y,&n);
- s=(x*y)/n;
- printf("%lf",dfs(x,y,n));
- return ;
bzoj1025
简单推一下就会发现跟博弈论鸡毛关系都没有
题目变成了
“求和为n的数列的最小公倍数种数”
然后随便D一下
- #include<iostream>
- #include<cstdio>
- #include<cstdlib>
- #include<algorithm>
- #include<cmath>
- #include<cstring>
- #define ll long long
- using namespace std;
- int n;
- int check[],pri[],cnt;
- ll dp[][],res;
- void laji()
- {
- for(int i=;i<=;i++)
- {
- if(!check[i])pri[++cnt]=i;
- for(int j=;j<=cnt;j++)
- {
- if(i*pri[j]>)break;
- check[i*pri[j]]=;
- if(i%pri[j]==)break;
- }
- }
- }
- int main()
- {
- scanf("%d",&n);
- laji();
- dp[][]=;
- for(int i=;i<=cnt;i++)
- {
- for(int j=;j<=n;j++)dp[i][j]=dp[i-][j];
- for(int j=pri[i];j<=n;j*=pri[i])
- for(int k=;k<=n-j;k++)dp[i][k+j]+=dp[i-][k];
- }
- for(int i=;i<=n;i++)res+=dp[cnt][i];
- cout<<res;
- }
bzoj1000~1025的更多相关文章
- UVA - 1025 A Spy in the Metro[DP DAG]
UVA - 1025 A Spy in the Metro Secret agent Maria was sent to Algorithms City to carry out an especia ...
- Light OJ 1025 - The Specials Menu(动态规划-区间dp)
题目链接:http://www.lightoj.com/volume_showproblem.php?problem=1025 题目大意:一串字符, 通过删除其中一些字符, 能够使这串字符变成回文串. ...
- HDU 1025 Constructing Roads In JGShining's Kingdom(求最长上升子序列nlogn算法)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1025 解题报告:先把输入按照r从小到大的顺序排个序,然后就转化成了求p的最长上升子序列问题了,当然按p ...
- HDU 1025 Constructing Roads In JGShining's Kingdom(二维LIS)
Constructing Roads In JGShining's Kingdom Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65 ...
- PAT乙级 1025. 反转链表 (25)
1025. 反转链表 (25) 时间限制 300 ms 内存限制 65536 kB 代码长度限制 8000 B 判题程序 Standard 作者 CHEN, Yue 给定一个常数K以及一个单链表L,请 ...
- uva 1025,城市的间谍
题目链接:https://uva.onlinejudge.org/external/10/1025.pdf 题意: 地铁是线性的,有n个站,编号(1~n),M1辆从左至右的车,和M2辆从右至左的车,发 ...
- 【BZOJ】【1025】【SCOI2009】游戏
DP/整数拆分 整个映射关系可以分解成几个循环(置换群的预备知识?),那么总行数就等于各个循环长度的最小公倍数+1(因为有个第一行的1~N).那么有多少种可能的排数就等于问有多少种可能的最小公倍数. ...
- bzoj 1025 [SCOI2009]游戏(置换群,DP)
[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=1025 [题意] 给定n,问1..n在不同的置换下变回原序列需要的不同排数有多少种. [ ...
- PAT-乙级-1025. 反转链表 (25)
1025. 反转链表 (25) 时间限制 300 ms 内存限制 65536 kB 代码长度限制 8000 B 判题程序 Standard 作者 CHEN, Yue 给定一个常数K以及一个单链表L,请 ...
随机推荐
- Android 适配(一)
一.Android适配基础参数 1.常见分辨率(px) oppx 2340x1080 oppR15 2280x1080 oppor11sp 2160*1080 ...
- WPF 支持集合绑定的控件
WPF 支持集合绑定的控件 ListBox ComboBox ListView DataGrid
- 【BZOJ1226】[SDOI2009]学校食堂Dining 状压DP
[BZOJ1226][SDOI2009]学校食堂Dining Description 小F 的学校在城市的一个偏僻角落,所有学生都只好在学校吃饭.学校有一个食堂,虽然简陋,但食堂大厨总能做出让同学们满 ...
- 【python】-- Socket粘包问题 ,解决粘包的几种方法、socket文件下载,md5值检验
上一篇随笔:“socket 接收大数据”,在win系统上能够运行,并且解决了大数据量的数据传输出现的问题,但是运行在linux系统上就会出现如下图所示的情况: 就是服务端两次发送给客户端的数据(第一次 ...
- linux 字符驱动
1 结构体说明: struct cdev { struct kobject kobj; // 每一个 cdev 都是一个 kobject st ...
- 安装Nginx 及使用
1.下载 Nginx wget http://nginx.org/download/nginx-1.10.3.tar.gz (稳定版) 2.提前下载好依赖包 openssl.zlib.pcre p ...
- Nodejs课堂笔记-第三课 构建一个nodejs的Docker镜像
本文由Vikings(http://www.cnblogs.com/vikings-blog/) 原创,转载请标明.谢谢! 因为一直做Linux有关的开发工作,所以不习惯在Windows平台编译和测试 ...
- Struts2学习总结(完整版)
一.搭建struts2环境 1.jar包的导入 主要是到 解压其中的一个工程,得到里面lib下包含的jar包 把这里的所有的jar包拷贝到项目的 WEB-INF目录下的lib文件夹下面. 2.配置st ...
- 添加启动项及常用Windows+R
常用Windows+R services.msc---本地服务设置 msconfig---系统配置实用程序 mspaint--------画图板 notepad--------打开记事本 Nslook ...
- 查看django的安装路径
查看django的安装路径 pip3 show django