亚历山大 8.29 需要题解~~~
这次是分题的题解~
分到两道要做的题 详细说一下:
I【CQOI2018】解锁屏幕 | ||
|
问题描述
输入格式
输出格式
AC
样例输入 1
4
0 0
1 1
2 2
3 3
样例输出 1
8
样例输入 2
4
0 0
0 1
0 2
1 0
样例输出 2
18
提示
#pragma GCC optimize(2) #pragma once %:pragma GCC optimize(3) %:pragma GCC optimize("Ofast") %:pragma GCC optimize("inline") %:pragma GCC optimize("-fgcse") %:pragma GCC optimize("-fgcse-lm") %:pragma GCC optimize("-fipa-sra") %:pragma GCC optimize("-ftree-pre") %:pragma GCC optimize("-ftree-vrp") %:pragma GCC optimize("-fpeephole2") %:pragma GCC optimize("-ffast-math") %:pragma GCC optimize("-fsched-spec") %:pragma GCC optimize("unroll-loops") %:pragma GCC optimize("-falign-jumps") %:pragma GCC optimize("-falign-loops") %:pragma GCC optimize("-falign-labels") %:pragma GCC optimize("-fdevirtualize") %:pragma GCC optimize("-fcaller-saves") %:pragma GCC optimize("-fcrossjumping") %:pragma GCC optimize("-fthread-jumps") %:pragma GCC optimize("-funroll-loops") %:pragma GCC optimize("-fwhole-program") %:pragma GCC optimize("-freorder-blocks") %:pragma GCC optimize("-fschedule-insns") %:pragma GCC optimize("inline-functions") %:pragma GCC optimize("-ftree-tail-merge") %:pragma GCC optimize("-fschedule-insns2") %:pragma GCC optimize("-fstrict-aliasing") %:pragma GCC optimize("-fstrict-overflow") %:pragma GCC optimize("-falign-functions") %:pragma GCC optimize("-fcse-skip-blocks") %:pragma GCC optimize("-fcse-follow-jumps") %:pragma GCC optimize("-fsched-interblock") %:pragma GCC optimize("-fpartial-inlining") %:pragma GCC optimize("no-stack-protector") %:pragma GCC optimize("-freorder-functions") %:pragma GCC optimize("-findirect-inlining") %:pragma GCC optimize("-fhoist-adjacent-loads") %:pragma GCC optimize("-frerun-cse-after-loop") %:pragma GCC optimize("inline-small-functions") %:pragma GCC optimize("-finline-small-functions") %:pragma GCC optimize("-ftree-switch-conversion") %:pragma GCC optimize("-foptimize-sibling-calls") %:pragma GCC optimize("-fexpensive-optimizations") %:pragma GCC optimize("-funsafe-loop-optimizations") %:pragma GCC optimize("inline-functions-called-once") %:pragma GCC optimize("-fdelete-null-pointer-checks") #include<bits/stdc++.h> #pragma GCC optimize(2) #define pii pair<int,int> #define mp make_pair #include<cctype> using namespace std; const int N=20,mod=100000007; int n,X[N],Y[N],a[N][N],f[N][1<<N],ans=0; bool vis[N][1<<N]; queue<pii> Q; char buf[1<<20],*p1,*p2; #define GC (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<20,stdin),p1==p2)?0:*p1++) template<class T> inline void read(T &n){ char ch=GC;T w=1,xx=0; while(!isdigit(ch)){if(ch=='-') w=-1;ch=GC;} while(isdigit(ch)){xx=(xx<<3)+(xx<<1)+(ch^48);ch=GC;} n=xx*w; } inline bool isright(int x) { int cnt=0; for(;x;x-=(x&(-x)))cnt++; return cnt>=4; } inline bool onit(int x,int s,int t) { if(X[x]<min(X[s],X[t]) || X[x]>max(X[s],X[t]) || Y[x]<min(Y[s],Y[t]) || Y[x]>max(Y[s],Y[t])) return 0; return ((X[x]-X[s])*(Y[t]-Y[x])-(X[t]-X[x])*(Y[x]-Y[s])==0); } inline bool check(int x,int s,int t) { return ((a[s][t]&x)==a[s][t]); } inline void Add(int &x,int y) { x+=y;if(x>=mod)x-=mod; } signed main() { read(n); for(register int i=0;i<n;i++)read(X[i]),read(Y[i]); for(register int i=0;i<n;i++) { for(register int j=0;j<n;j++) if(i!=j) { for(register int k=0;k<n;k++) if(k!=i && k!=j && onit(k,i,j)) a[i][j]+=(1<<k); } } for(register int i=0;i<n;i++) { vis[i][1<<i]=1;f[i][1<<i]=1; Q.push(mp(i,1<<i)); } while(!Q.empty()) { int x=Q.front().first,y=Q.front().second; Q.pop(); if(isright(y)) Add(ans,f[x][y]); for(register int i=0,j=1;i<n;i++,j<<=1) if((j&y)==0) { if(!check(y,x,i)) continue; if(!vis[i][j|y])vis[i][j|y]=1,Q.push(mp(i,j|y)); Add(f[i][j|y],f[x][y]); } } printf("%d\n",ans); }
先附上一个我呕心沥血的代码 但是我想说 nkoj上依然50t了
做这道题我感觉我已经学习了很多基础优化玄学方法
真的是输入输出优化都做了,inline ,register,全都改了但是还是不行
但是!敲黑板:这道题优化最好的方法就是少传数 还有就是mod很耗时间 所以也要优化一下!!!
所以说能少写一个函数就少写一个
这道题在落谷上交了很多次 原因是可能在落谷上过了,但是开了o2优化 所以要在nkoj上过不一定
楼上代码我在交的时候最大时间1024ms 但是奈何1000ms 所以没有过。
这道题我们需要额外注意的就是要再判断一下 1.当前是否连接4个点2.是否将两点之间的点连完算完。3.是否跳点连接 (其实同二)
但是由于这道题爆炸卡常 所以建议大家把这几个就写在main函数里。
另外 我们不能每次直接mod
为了优化 可以判断是否需要mod以后再mod!
下面是双ac代码(落谷,nkoj都可以不用开优化挂就过)
#include<bits/stdc++.h> #define ll long long #define mod 1e8+7 using namespace std; struct dian{int x,y;}a[25]; int n,place[25][25],x[25],y[25],dp[25][10786005],t,s; ll ans; ll modsss(ll x) { if(x>mod)x-=mod; return x; } int main() { scanf("%d",&n); for(int i=0;i<n;i++)scanf("%d%d",&a[i].x,&a[i].y); for(int i=0;i<n;i++) for(int j=0;j<n;j++) for(int k=0;k<n;k++) if(k!=i&&k!=j&&a[k].x>=min(a[i].x,a[j].x)&&a[k].x<=max(a[i].x,a[j].x)&& a[k].y>=min(a[i].y,a[j].y)&&a[k].y<=max(a[i].y,a[j].y)&& (a[k].y-a[i].y)*(a[j].x-a[i].x)==(a[j].y-a[i].y)*(a[k].x-a[i].x))place[i][j]|=(1<<k); for(int i=0;i<n;i++)dp[i][1<<i]=1; for(int t=0;t<(1<<n);t++) for(int s=0;s<n;s++) { if(!(t&(1<<s))||!dp[s][t])continue; for(int i=0;i<n;i++) { if((1<<i)&t)continue;//cout<<i<<endl; if((place[s][i]&t)!=place[s][i])continue; dp[i][t|(1<<i)]+=dp[s][t]; if(dp[i][t|(1<<i)]>=mod)dp[i][t|(1<<i)]-=mod; } } for(int t=0;t<(1<<n);t++) { int tot=0,pp=t; for(;pp;pp-=pp&-pp)tot++; if(tot>3) for(int i=0;i<n;i++)if((1<<i)&t) { ans+=dp[i][t]; ans=modsss(ans); } } printf("%lld\n",ans); }
接下来是
M最长上升子序列 | ||
|
问题描述
给出1~n的一个排列的一个最长上升子序列,求原排列可能的种类数。
输入格式
第一行一个整数n。
第二行一个整数k,表示最长上升子序列的长度。
第三行k个整数,表示这个最长上升子序列。
输出格式
第一行一个整数,表示原排列可能的种类数。
样例输入 1
5
3
1 3 4
样例输出 1
11
样例输入 2
11
4
1 2 3 4
样例输出 2
256288
提示
【样例1说明】
11种排列分别为(1, 3, 2, 5, 4), (1, 3, 5, 2, 4), (1, 3, 5, 4, 2), (1, 5, 3, 2, 4), (1, 5, 3, 4, 2), (2, 1, 3, 5, 4), (2, 1, 5, 3, 4), (2, 5, 1, 3, 4), (5, 1, 3, 2, 4), (5, 1, 3, 4, 2), (5, 2, 1, 3, 4)。
【数据规模和约定】
对于30%的数据,1 <= n <= 11。
对于70%的数据,1 <= n <= 14。
对于100%的数据,1 <= n <= 15,答案小于2^31。
#include<stdio.h> #include<bits/stdc++.h> #include<cctype> using namespace std; int x,n,m,maxx,s,tot,now,l,h[20],cnt[20],pos,f[14349000],a[20],ans; queue<int >q; char buf[1<<20],*p1,*p2; #define GC (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<20,stdin),p1==p2)?0:*p1++) template<class T> inline void read(T &n){ char ch=GC;T w=1,x=0; while(!isdigit(ch)){if(ch=='-') w=-1;ch=GC;} while(isdigit(ch)){x=(x<<3)+(x<<1)+(ch^48);ch=GC;} n = x*w; } int main() { f[0]=1,ans=0,h[0]=cnt[0]=1; //read(n),read(m); cin>>n>>m; for (int i=1;i<=n;i++) h[i]=h[i-1]*2,cnt[i]=cnt[i-1]*3; for (int i=1;i<=m;i++) //read(x), cin>>x, pos+=h[x-1]; q.push(0); while (!q.empty()) { s=q.front();q.pop(); maxx=0,now=0,tot=0; for (int i=n-1;i>=0;i--) { a[i]=s/cnt[i]%3; maxx+=a[i]==2; tot|=(!a[i]); if (!a[i]&&(pos&h[i])) now=i; } ans+=!tot&&maxx==m?f[s]:0; if (tot){ l=0; for (int i=n-1;i>=0;i--) { l=a[i]==2?i:l; if (!(a[i]||(pos&h[i])&&i!=now||!l&&maxx==m)){ int s1=s+(cnt[i]<<1); s1-=(l>0)?cnt[l]:0; if (!f[s1]) q.push(s1); f[s1]+=f[s]; } } } } cout<<ans; }