1032 最长回文子串
#include <bits/stdc++.h> #define pb push_back #define se second #define fs first #define sq(x) (x)*(x) #define eps 0.000000001 using namespace std; typedef long long ll; typedef pair<ll,ll> P; const int maxv=1e6+3000; char r[maxv]; char s[maxv*2]; int p[maxv*2]; int n; int len; void manacher(){ s[0]='&'; for(int i=0;i<len;i++){ s[2*i+1]='#'; s[2*i+2]=r[i]; } s[2*len+1]='#'; s[2*len+2]='*'; int mx=0,mxid=0; for(int i=1;i<=2*len;i++){ if(mx>i){ p[i]=min(p[mxid*2-i],mx-i); }else{ p[i]=1; } for(;s[i-p[i]]==s[i+p[i]];p[i]++); if(p[i]+i>mx){ mx=p[i]+i; mxid=i; } } } int main(){ /// freopen("/home/files/CppFiles/in","r",stdin); cin>>n; while(n--){ scanf("%s",r); len=strlen(r); manacher(); int ans=0; for(int i=1;i<=2*len;i++){ ans=max(ans,p[i]); } cout<<ans-1<<endl; } return 0; }
1014 Trie
#include <bits/stdc++.h> #define pb push_back #define se second #define fs first #define sq(x) (x)*(x) #define eps 0.000000001 using namespace std; typedef long long ll; typedef pair<ll,ll> P; const int csize=26; const int maxv=1e5+3000; struct Node{ Node *ch[csize]; int val; int num; }pool[maxv*3]; int ph=0; Node *newNode(){ for(int i=0;i<csize;i++){ pool[ph].ch[i]=NULL; } pool[ph].val=pool[ph].num=0; return &pool[ph++]; } Node *root=newNode(); void insert(Node *n,char *s,int len){ for(int i=0;i<len;i++){ if(n->ch[s[i]-'a']==NULL) n->ch[s[i]-'a']=newNode(); n=n->ch[s[i]-'a']; } n->val++; } void dfs(Node *n){ n->num=n->val; for(int i=0;i<csize;i++){ if(n->ch[i]==NULL) continue; dfs(n->ch[i]); n->num+=n->ch[i]->num; } } int query(Node *n,char *s,int len){ for(int i=0;i<len;i++){ if(n->ch[s[i]-'a']==NULL) return 0; n=n->ch[s[i]-'a']; } return n->num; } int n; char r[maxv]; int main(){ // freopen("/home/files/CppFiles/in","r",stdin); cin>>n; for(int i=0;i<n;i++){ scanf("%s",r); int len=strlen(r); insert(root,r,len); } dfs(root); int q; cin>>q; for(int i=0;i<q;i++){ scanf("%s",r); int len=strlen(r); printf("%d ",query(root,r,len)); } return 0; }
1015 KMP(大白模板
#include <bits/stdc++.h> #define pb push_back #define se second #define fs first #define sq(x) (x)*(x) #define eps 0.000000001 using namespace std; typedef long long ll; //typedef pair<ll,ll> P; const int maxv=1e6+3000; char P[maxv]; char T[maxv]; int fail[maxv]; void getFail(char *P,int *f){ int len=strlen(P); f[0]=f[1]=0; for(int i=1;i<len;i++){ int j=f[i]; while(j&&P[i]!=P[j]) j=f[j]; f[i+1]=(P[i]==P[j]?j+1:0); } } int ans=0; void match(char *T,char *P,int *f){ int n=strlen(T),m=strlen(P); int j=0; for(int i=0;i<n;i++){ while(j&&P[j]!=T[i]) j=f[j]; if(P[j]==T[i]) j++; if(j==m) ans++; } } int N; int n; int main(){ freopen("/home/files/CppFiles/in","r",stdin); cin>>n; while(n--){ scanf("%s%s",P,T); ans=0; getFail(P,fail); match(T,P,fail); cout<<ans<<endl; } return 0; }
1036 AC自动机(大白模板
#include <bits/stdc++.h> #define pb push_back #define se second #define fs first #define sq(x) (x)*(x) #define eps 0.000000001 using namespace std; typedef long long ll; typedef pair<ll,ll> P; const int maxv=1e6+3000; const int csize=26; int ch[maxv*4][csize]; int val[maxv*4]; int sz=0; void Tclear(){ sz=1; memset(ch[0],0,sizeof ch[0]); } void insert(char *s,int v){ int u=0,n=strlen(s); for(int i=0;i<n;i++){ int c=s[i]-'a'; if(!ch[u][c]){ memset(ch[sz],0,sizeof ch[sz]); val[sz]=0; ch[u][c]=sz++; } u=ch[u][c]; } val[u]=v; } int f[maxv*4]; int last[maxv*4]; queue<int> Q; void getFail(){ f[0]=0; for(int c=0;c<csize;c++){ int u=ch[0][c]; if(u){ f[u]=0; Q.push(u); } } while(!Q.empty()){ int r=Q.front();Q.pop(); for(int c=0;c<csize;c++){ int u=ch[r][c]; if(!u) continue; Q.push(u); int v=f[r]; while(v&&!ch[v][c]) v=f[v]; f[u]=ch[v][c]; } } } bool find(char *T){ int n=strlen(T); int j=0; for(int i=0;i<n;i++){ int c=T[i]-'a'; while(j&&!ch[j][c]) j=f[j]; j=ch[j][c]; if(val[j]) return 1; } return 0; } int N; char r[maxv]; int main(){ freopen("/home/files/CppFiles/in","r",stdin); Tclear(); cin>>N; for(int i=0;i<N;i++){ scanf("%s",r); insert(r,1); } getFail(); scanf("%s",r); if(find(r)){ cout<<"YES"<<endl; }else{ cout<<"NO"<<endl; } return 0; }
1067 离线lca,tarjan算法(这题人名处理有点恶心。。。。
#include <bits/stdc++.h> #define pb push_back #define se second #define fs first #define sq(x) (x)*(x) #define eps 0.000000001 #define LB lower_bound #define IINF (1<<29) #define LINF (1ll<<59) using namespace std; typedef long long ll; typedef pair<ll,ll> P; const int maxv=1e5+300; string father[maxv],son[maxv]; int n,m; set<string> S; map<string,int> idx; map<int,string> dir; vector<P> qu[maxv]; vector<int> G[maxv]; int ans[maxv]; int fa[maxv]; int find(int x){ if(fa[x]==x) return x; return fa[x]=find(fa[x]); } void setFa(int x,int f){ fa[find(x)]=f; } bool vis[maxv]; void dfs(int v,int f){ for(int i=0;i<G[v].size();i++){ int u=G[v][i]; if(u==f) continue; dfs(u,v); setFa(u,v); } vis[v]=1; for(int i=0;i<qu[v].size();i++){ int u=qu[v][i].fs,o=qu[v][i].se; if(vis[u]){ ans[o]=find(u); } } } void init(){ for(int i=0;i<maxv;i++){ fa[i]=i; } } int main(){ freopen("/home/files/CppFiles/in","r",stdin); init(); cin>>n; for(int i=0;i<n;i++){ cin>>father[i]>>son[i]; if(S.find(father[i])==S.end()){ idx[father[i]]=S.size()+1; dir[S.size()+1]=father[i]; S.insert(father[i]); } if(S.find(son[i])==S.end()){ idx[son[i]]=S.size()+1; dir[S.size()+1]=son[i]; S.insert(son[i]); } G[idx[father[i]]].pb(idx[son[i]]); } cin>>m; string a,b; for(int i=0;i<m;i++){ cin>>a>>b; qu[idx[a]].pb(P(idx[b],i)); qu[idx[b]].pb(P(idx[a],i)); } dfs(1,-1); for(int i=0;i<m;i++){ cout<<dir[ans[i]]<<endl; } }
题目:给和1连通的一部分节点染色,问能得到的最大权值和为多少。
思路:树形dp,注意每个节点可以进行背包(不是题解里说的无限背包。。。明明就是01背包。。。),每个子树可以选0~m个节点,dp的顺序应该是背包容量从大到小,物品随意(容量循环在外面),如果dp方向搞反就是无限背包。
#include <bits/stdc++.h> #define pb push_back #define se second #define fs first #define sq(x) (x)*(x) #define eps 0.000000001 #define LB lower_bound #define IINF (1<<29) #define LINF (1ll<<59) using namespace std; typedef long long ll; typedef pair<ll,ll> P; const int maxv=105; int n,m; int val[maxv]; vector<int> G[maxv]; int dp[maxv][maxv]; void dfs(int v,int f){ dp[v][0]=0; dp[v][1]=val[v]; for(int i=0;i<G[v].size();i++){ int u=G[v][i]; if(u==f) continue; dfs(u,v); for(int j=m;j>0;j--){ for(int k=1;k<m;k++){ if(j-k>0) dp[v][j]=max(dp[v][j],dp[v][j-k]+dp[u][k]); } } } } int main(){ freopen("/home/files/CppFiles/in","r",stdin); cin>>n>>m; for(int i=1;i<=n;i++){ scanf("%d",val+i); } for(int i=0;i<n-1;i++){ int a,b; scanf("%d%d",&a,&b); G[a].pb(b); G[b].pb(a); } dfs(1,-1); cout<<dp[1][m]<<endl; return 0; }
1078 线段树的区间修改,lazy标记
题目:更改某区间的所有数,询问区间和。
思路:借助lazy标记维护区间,每次查询和修改经过节点时下传标记。
#include <bits/stdc++.h> #define pb push_back #define se second #define fs first #define sq(x) (x)*(x) #define eps 0.000000001 #define LB lower_bound #define IINF (1<<29) #define LINF (1ll<<59) using namespace std; typedef long long ll; typedef pair<ll,ll> P; const int maxv=1e5+300; struct Node{ int l,r; bool lazy; int sum,val; Node *ch[2]; }pool[maxv*5]; int ph=0; Node *newNode(){ Node *n=&pool[ph++]; n->lazy=0; return n; } Node *root=newNode(); int w[maxv]; void build(Node *n,int l,int r){ n->l=l,n->r=r; if(r-l<=1){ n->sum=w[l]; return; } int mid=(r+l)/2; n->ch[0]=newNode(); n->ch[1]=newNode(); build(n->ch[0],l,mid); build(n->ch[1],mid,r); n->sum=n->ch[0]->sum+n->ch[1]->sum; return; } void pushdown(Node *n){ if(n->r-n->l<=1) return; Node *chl=n->ch[0],*chr=n->ch[1]; if(n->lazy){ chl->lazy=1; chr->lazy=1; chl->val=n->val; chr->val=n->val; chl->sum=(chl->r-chl->l)*n->val; chr->sum=(chr->r-chr->l)*n->val; n->lazy=0; } } void change(Node *n,int a,int b,int x){ pushdown(n); int l=n->l,r=n->r; Node *chr=n->ch[1],*chl=n->ch[0]; if(l>=b||a>=r) return; if(l>=a&&b>=r){ n->lazy=1; n->val=x; n->sum=(r-l)*x; return; } change(chl,a,b,x); change(chr,a,b,x); n->sum=chr->sum+chl->sum; return; } int query(Node *n,int a,int b){ pushdown(n); int l=n->l,r=n->r; if(l>=b||a>=r) return 0; if(l>=a&&b>=r) return n->sum; return query(n->ch[0],a,b)+query(n->ch[1],a,b); } int n; int main(){ freopen("/home/files/CppFiles/in","r",stdin); cin>>n; for(int i=0;i<n;i++){ int ss; scanf("%d",&ss); w[i]=ss; } build(root,0,n); int q; cin>>q; while(q--){ int a,b,c,d; scanf("%d%d%d",&a,&b,&c); if(a==0){ printf("%d ",query(root,b-1,c)); }else{ scanf("%d",&d); change(root,b-1,c,d); } } return 0; }
1080 同时维护线段树的两个区间修改
题目:两种操作分别是把某区间的数都变为某个值,以及把这个区间的值全部加x,求每次操作后询问区间和。
思路:维护两个lazy tag,分别是加上的值和直接更改的值。写的时候出现了两个问题,一个是add值不能直接覆盖,应该采用加法,因为一个节点可能多次接受从父节点push下来的add值但是未向下push。然后最开始直接把两个值分开处理的,这样有可能一个节点同时有add和val两个标记,但是两个标记push的顺序不同,结果截然不同。实际上如果已经有val标签,那么add的值直接加到val上,如果有add的标签再加val就直接清0.这样任何时候一个节点都不会有两个标签,并且保证结果正确。
#include <bits/stdc++.h> #define pb push_back #define se second #define fs first #define sq(x) (x)*(x) #define eps 0.000000001 #define LB lower_bound #define IINF (1<<29) #define LINF (1ll<<59) using namespace std; typedef long long ll; typedef pair<ll,ll> P; const int maxv=1e5+300; struct Node{ int l,r,len; int val,add,sum; bool lazyv,lazya; Node *ch[2]; }pool[maxv*5]; int ph=0; inline Node *newNode(){ Node *n=&pool[ph++]; n->add=n->lazya=n->lazyv=0; return n; } Node *root=newNode(); int w[maxv]; void build(Node *n,int l,int r){ n->l=l,n->r=r,n->len=r-l; if(r-l<=1){ n->sum=w[l]; return; } Node *&chr=n->ch[1],*&chl=n->ch[0]; chr=newNode(),chl=newNode(); build(chl,l,(r+l)/2); build(chr,(r+l)/2,r); n->sum=chr->sum+chl->sum; return; } inline void pushDown(Node *n){ if(n->len<=1) return; Node *chl=n->ch[0],*chr=n->ch[1]; int add=n->add,val=n->val; if(n->lazya){ n->lazya=0; n->add=0; if(chl->lazyv) chl->val+=add; else{ chl->lazya=1; chl->add+=add; } if(chr->lazyv) chr->val+=add; else{ chr->lazya=1; chr->add+=add; } chr->sum+=add*chr->len; chl->sum+=add*chl->len; } if(n->lazyv){ n->lazyv=0; chl->val=val; chr->val=val; chr->lazyv=chl->lazyv=1; chr->lazya=chl->lazya=0; chr->add=chl->add=0; chl->sum=chl->len*val; chr->sum=chr->len*val; } } void changea(Node *n,int a,int b,int x){ pushDown(n); int l=n->l,r=n->r; if(l>=b||a>=r) return; if(a<=l&&b>=r){ n->lazya=1; n->add+=x; n->sum+=n->len*x; return; } Node *chr=n->ch[1],*chl=n->ch[0]; changea(chl,a,b,x); changea(chr,a,b,x); n->sum=chr->sum+chl->sum; } void changev(Node *n,int a,int b,int x){ pushDown(n); int l=n->l,r=n->r; if(l>=b||a>=r) return; if(a<=l&&b>=r){ n->lazyv=1; n->val=x; n->sum=n->len*x; return; } Node *chr=n->ch[1],*chl=n->ch[0]; changev(chl,a,b,x); changev(chr,a,b,x); n->sum=chr->sum+chl->sum; } int query(Node *n,int a,int b){ pushDown(n); Node *chl=n->ch[0],*chr=n->ch[1]; int l=n->l,r=n->r; if(l>=b||a>=r) return 0; if(a<=l&&b>=r) return n->sum; return query(chl,a,b)+query(chr,a,b); } int n,m; int main(){ freopen("/home/files/CppFiles/in","r",stdin); cin>>n>>m; for(int i=0;i<n+1;i++){ scanf("%d",&w[i]); } build(root,0,n+1); while(m--){ int a,b,c,d; scanf("%d%d%d%d",&a,&b,&c,&d); if(a==0){ changea(root,b,c+1,d); }else{ changev(root,b,c+1,d); } printf("%d ",query(root,0,n+1)); } return 0; }
1183 割顶,割边
题目:如题。
思路:tarjan算法,利用时间戳求出每个点能够通过回边到达的最小节点,即可判断。一个特殊处理是根节点。此外,需要注意每个节点都可能会重复push,需要谨慎去重。
#include <bits/stdc++.h> #define pb push_back #define se second #define fs first #define sq(x) (x)*(x) #define eps 0.000000001 #define LB lower_bound #define IINF (1<<29) #define LINF (1ll<<59) #define bk back() using namespace std; typedef long long ll; typedef pair<ll,ll> P; const int maxn=2e4+400; int n,m; vector<int> G[maxn]; int od[maxn]; int low[maxn]; int clo=0; vector<P> ce; vector<int> cp; bool used[maxn]; void dfs(int v,int f){ int chn=0; low[v]=od[v]=++clo; for(int i=0;i<G[v].size();i++){ int u=G[v][i]; if(u==f) continue; if(!od[u]){ chn++; dfs(u,v); low[v]=min(low[v],low[u]); if(f==-1&&chn==2) cp.pb(v); if(f!=-1&&low[u]>=od[v]&&!used[v]) cp.pb(v),used[v]=1;///note:may be more than one time pushed if(low[u]>od[v]){ ce.pb(P(u,v)); if(u>v) swap(ce.bk.fs,ce.bk.se); } } else low[v]=min(low[v],od[u]); } } int main(){ freopen("/home/files/CppFiles/in","r",stdin); cin>>n>>m; for(int i=0;i<m;i++){ int a,b; scanf("%d%d",&a,&b); G[a].pb(b); G[b].pb(a); } dfs(1,-1); sort(ce.begin(),ce.end()); sort(cp.begin(),cp.end()); for(int i=0;i<cp.size();i++){ cout<<cp[i]; if(i<cp.size()-1) cout<<" "; } if(!cp.size()) puts("Null"); else puts(""); for(int i=0;i<ce.size();i++){ cout<<ce[i].fs<<" "<<ce[i].se<<endl; } return 0; }
1184 双连通分量
思路: 因为low[u] == dfn[u],对(parent[u],u)来说有dfn[u] > dfn[ parent[u] ],因此low[u] > dfn[ parent[u] ] ,所以(parent[u],u)一定是一个桥,那么此时栈内在u之前入栈的点和u被该桥分割开 ,则u和之后入栈的节点属于同一个组 将从u到栈顶所有的元素标记为一个组,并弹出这些元素。
#include <bits/stdc++.h> #define pb push_back #define se second #define fs first #define sq(x) (x)*(x) #define eps 0.000000001 #define LB lower_bound #define IINF (1<<29) #define LINF (1ll<<59) #define bk back() using namespace std; typedef long long ll; typedef pair<ll,ll> P; const int maxn=2e4+300; int n,m; vector<int> G[maxn]; int stk[maxn]; int stk2[maxn]; int stop2=0; int stop=0; int od[maxn],low[maxn]; int clo=0; vector< vector<int> > bcc; void dfs(int v,int f){ stk[stop++]=v; int chn=0; low[v]=od[v]=++clo; for(int i=0;i<G[v].size();i++){ int u=G[v][i]; if(u==f) continue; if(!od[u]){ chn++; dfs(u,v); low[v]=min(low[v],low[u]); }else low[v]=min(low[v],od[u]); } if(low[v]==od[v]&&f!=-1){ bcc.pb(vector<int>()); while(stk[stop-1]!=v){ stop--; bcc.bk.pb(stk[stop]); } bcc.bk.pb(v); stop--; } } int main(){ freopen("/home/files/CppFiles/in","r",stdin); cin>>n>>m; for(int i=0;i<m;i++){ int a,b; scanf("%d%d",&a,&b); G[a].pb(b); G[b].pb(a); } dfs(1,-1); bcc.pb(vector<int>()); while(stop>0) bcc.bk.pb(stk[--stop]); for(int i=0;i<bcc.size();i++) sort(bcc[i].begin(),bcc[i].end()); int *ans=new int[n+1]; for(int i=0;i<bcc.size();i++){ for(int j=0;j<bcc[i].size();j++){ ans[bcc[i][j]]=bcc[i][0]; } } cout<<bcc.size()<<endl; for(int i=1;i<=n;i++){ cout<<ans[i]<<" "; } return 0; }
1174 拓扑排序
思路:每次删去入度为0的点。此算法可以判断有向图中是否有圈,也可进行拓扑排序,复杂度较低。
#include <bits/stdc++.h> #define pb push_back #define se second #define fs first #define sq(x) (x)*(x) #define eps 0.000000001 #define LB lower_bound #define IINF (1<<29) #define LINF (1ll<<59) #define bk back() #define PB pop_back using namespace std; typedef long long ll; typedef pair<ll,ll> P; const int maxn=1e5+400; int T; int n,m; int d[maxn],del[maxn]; vector<int> G[maxn]; void clear(){ for(int i=0;i<maxn;i++){ G[i].clear(); } memset(d,0,sizeof d); memset(del,0,sizeof del); } queue<int> Q; void topo(){ for(int i=1;i<=n;i++){ if(d[i]==0){ Q.push(i); } } int cont=0; while(!Q.empty()){ int v=Q.front();Q.pop(); del[v]=1; cont++; while(!G[v].empty()&&del[G[v].bk]) G[v].PB(); for(int i=0;i<G[v].size();i++){ int u=G[v][i]; if(del[u]) continue; d[u]--; if(d[u]==0) Q.push(u); } } if(cont<n){ puts("Wrong"); }else{ puts("Correct"); } } int main(){ freopen("/home/files/CppFiles/in","r",stdin); cin>>T; while(T--){ clear(); cin>>n>>m; for(int i=0;i<m;i++){ int a,b; scanf("%d%d",&a,&b); G[a].pb(b); d[b]++; } topo(); } return 0; }
1185 强连通分量分解,拓扑排序ordfs
思路:分解强连通分量,然后就是树上的dp了。自己yy了一个貌似复杂度还可以的缩点方法。
#include <bits/stdc++.h> #define pb push_back #define se second #define fs first #define sq(x) (x)*(x) #define eps 0.000000001 #define LB lower_bound #define IINF (1<<29) #define LINF (1ll<<59) #define bk back() #define PB pop_back using namespace std; typedef long long ll; typedef pair<ll,ll> P; const int maxn=2e4+300; int n,m; vector<int> G[maxn]; int w[maxn]; int clo=0; int stk[maxn],top=0,scc_id[maxn]; int low[maxn],od[maxn],instk[maxn]; int scc_w[maxn]; int scc_num=0; vector<int> scc_p[maxn]; void scc_dfs(int v){ instk[v]=od[v]=low[v]=++clo; stk[top++]=v; for(int i=0;i<G[v].size();i++){ int u=G[v][i]; if(!od[u]){ scc_dfs(u); low[v]=min(low[v],low[u]); }else if(instk[u]){ low[v]=min(low[v],od[u]); } } if(low[v]==od[v]){ ++scc_num; do{ scc_id[stk[--top]]=scc_num; scc_w[scc_num]+=w[stk[top]]; instk[stk[top]]=0; scc_p[scc_num].pb(stk[top]); }while(stk[top]!=v); } } vector<int> nG[maxn]; int d[maxn]; void rebuild(){ for(int i=1;i<=scc_num;i++){ for(int j=0;j<scc_p[i].size();j++){ int u=scc_p[i][j]; for(int k=0;k<G[u].size();k++){ int v=G[u][k]; if(scc_id[v]!=scc_id[u]){ nG[i].pb(scc_id[v]); d[scc_id[v]]++; } } } } } queue<int> Q; int dp[maxn]; void topo(){ for(int i=1;i<=scc_num;i++){ if(d[i]==0){ Q.push(i); dp[i]=scc_w[i]; } } while(!Q.empty()){ int v=Q.front();Q.pop(); for(int i=0;i<nG[v].size();i++){ int u=nG[v][i]; dp[u]=max(dp[u],dp[v]+scc_w[u]); d[u]--; if(d[u]==0){ Q.push(u); } } } } int main(){ freopen("/home/files/CppFiles/in","r",stdin); cin>>n>>m; for(int i=1;i<=n;i++) scanf("%d",w+i); for(int i=0;i<m;i++){ int a,b; scanf("%d%d",&a,&b); G[a].pb(b); } scc_dfs(1); rebuild(); topo(); int ans=0; for(int i=1;i<=scc_num;i++) ans=max(ans,dp[i]); cout<<ans<<endl; return 0; }
1195 高斯消元(hiho找的板子
/* *@author: Cwind *http://www.cnblogs.com/Cw-trip/ */ //#pragma comment(linker, "/STACK:102400000,102400000") #include <iostream> #include <map> #include <algorithm> #include <cstdio> #include <cstring> #include <cstdlib> #include <vector> #include <queue> #include <stack> #include <functional> #include <set> #include <cmath> #define pb push_back #define PB pop_back #define fs first #define se second #define sq(x) (x)*(x) #define IINF (1<<29) using namespace std; typedef long long ll; typedef pair<ll,ll> P; //////////////////////////////////////////////////////// const int MAX_N = 567; const int MAX_M = 1024; const double EPS = 1e-5; struct Answer { double x; int id; }; Answer ans[MAX_N]; double a[MAX_M][MAX_N]; double b[MAX_M]; double tmp[MAX_N]; void swap_line(int i, int j) { memcpy(tmp, a[i], sizeof(tmp)); memcpy(a[j], a[i], sizeof(tmp)); memcpy(a[i], tmp, sizeof(tmp)); swap(b[i], b[j]); swap(ans[i], ans[j]); } int Gauss(int n, int m) { // 处理出上三角矩阵 for (int i = 1; i <= n; i++) { bool flag = false; for (int j = i; j <= m; j++) { // 从第i行开始,找到第i列不等于0的行j if (fabs(a[j][i]) > EPS) { swap_line(j, i); // 交换第i行和第j行 flag = true; break; } } // 若无法找到,则存在多个解 if (!flag) return 2; // 解多于一个 // 消除第i+1行到第M行的第i列 for (int j = i + 1; j <= m; j++) tmp[j] = a[j][i] / a[i][i]; for (int j = i + 1; j <= m; j++) { for (int k = 1; k <= n; k++) { a[j][k] = a[j][k] - a[i][k] * tmp[j]; } b[j] = b[j] - b[i] * tmp[j]; } } // 检查是否无解,即存在 0 = x 的情况 for (int i = 1; i <= m; i++) { if (fabs(b[i]) < EPS) continue; bool all_zero = true; // 第i行系数均为0? for (int j = 1; j <= n; j++) { if (fabs(a[i][j]) > EPS) { all_zero = false; break; } } if (all_zero) return 0; // 无解 } // 此时存在唯一解 // 由于每一行都比前一行少一个系数,所以在M行中只有前N行有系数 // 从第N行开始处理每一行的解 for (int i = n; i >= 1; i--) { // 利用已经计算出的结果,将第i行中第i+1列至第N列的系数消除 for (int j = i + 1; j <= n; j++) { b[i] = b[i] - a[i][j] * ans[j].x; a[i][j] = 0; } ans[i].x = b[i] / a[i][i]; } return 1; // 唯一解 } bool id_order(const Answer& a, const Answer& b) { return a.id < b.id; } //Zconst int maxn=505; int n,m; int main(){ /// freopen("/home/files/CppFiles/in","r",stdin); //freopen("/home/files/CppFiles/out","w",stdout); cin>>n>>m; for(int i=1;i<=m;i++){ for(int j=1;j<=n;j++){ scanf("%lf",&a[i][j]); } scanf("%lf",&b[i]); ans[i].id=i; } int val=Gauss(n,m); if(val==0){ puts("No solutions"); }else if(val==2){ puts("Many solutions"); }else{ sort(ans+1,ans+n+1,id_order); for(int i=1;i<=n;i++){ printf("%d ",int(ans[i].x + 0.5)); } } return 0; }
/* * @author: Cwind * http://www.cnblogs.com/Cw-trip/ */ #include <bits/stdc++.h> #define pb push_back #define se second #define fs first #define sq(x) (x)*(x) #define eps 0.000000001 #define LB lower_bound #define IINF (1<<29) #define LINF (1ll<<59) #define bk back() #define PB pop_back using namespace std; typedef long long ll; typedef pair<ll,ll> P; int a[110][110]; int x[110]; int free_x[110]; int free_num; //返回值为-1表示无解,为0是唯一解,否则返回自由变元个数 int Gauss_xor(int equ,int var) { int max_r, col, k; free_num = 0; for(k = 0, col = 0; k < equ && col < var; k++, col++) { max_r = k; for(int i = k+1 ; i < equ; i++) if(abs(a[i][col]) > abs(a[max_r][col])) max_r = i; if(a[max_r][col] == 0) { k--; free_x[free_num++] = col; //自由变元 continue; } if(max_r != k) { for(int j = col; j < var+1; j++) swap(a[k][j],a[max_r][j]); } for(int i = k+1; i < equ;i++) if(a[i][col] != 0) for(int j = col; j < var+1;j++) a[i][j] ^= a[k][j]; } for(int i = k;i < equ;i++) if(a[i][col] != 0) return -1; if(k < var)return var-k; for(int i = var-1; i >= 0;i--) { x[i] = a[i][var]; for(int j = i+1; j < var;j++) x[i] ^= (a[i][j] && x[j]); } return 0; } int drx[4]={1,-1,0,0}; int dry[4]={0,0,-1,1}; void geta(){ for(int i=0;i<5;i++){ for(int j=0;j<6;j++){ a[i*6+j][i*6+j]=1; for(int k=0;k<4;k++){ int dx=i+drx[k],dy=j+dry[k]; if(dx>=0&&dx<5&&dy>=0&&dy<6){ a[i*6+j][dx*6+dy]=1; } } } } } char r[10]; bool grid[10][10]; int main(){ ////freopen("/home/files/CppFiles/in","r",stdin); geta(); /* for(int i=0;i<30;i++){ for(int j=0;j<30;j++){ printf("%d",a[i][j]); } puts(""); }*/ for(int i=0;i<5;i++){ scanf("%s",r); for(int j=0;j<6;j++){ grid[i][j]=r[j]-'0'; } } for(int i=0;i<30;i++){ a[i][30]=1^grid[i/6][i%6]; } Gauss_xor(30,30); int num=0; for(int i=0;i<30;i++) if(x[i]) num++; cout<<num<<endl; for(int i=0;i<30;i++){ if(x[i]){ printf("%d %d ",i/6+1,i%6+1); } } return 0; }