1001:Inversion
模版题,求逆序数对。有多少逆序数对,就可以剪掉多少。
1003:Least common multiple
对于每一个子集,lcm为2的a的最大值次方*3的b的最大值次方。
所以我们只需要求出以某个b为b的最大值的时候,a的最大值的分布情况即可。
我们先把b从小到大排序。
对于某一个b,我门只需要求出之前出现过的a比当前a小的数量为x;
那么就可知对于这些a的子集,为2^x个,并且,每个子集a的最大值都为当前a。
我么还需要求出对于大于当前a的a有多少个比a小的数,我们可以用线段树逐步维护。
#include <iostream> #include<stdio.h> #include<vector> #include<queue> #include<stack> #include<string.h> #include<algorithm> #include<math.h> #include<map> using namespace std; #define LL long long #define lcm(a,b) (a*b/gcd(a,b)) #define maxn 110000 #define lson l,(l+r)/2,rt<<1 #define rson (l+r)/2+1,r,rt<<1|1 struct list { int a,b; friend bool operator <(const list &a,const list &b) { return a.b<b.b; } }p[maxn]; int cmp(list a,list b) { return a.a<b.a; } int ed[maxn]; LL num[maxn<<2]; LL sum[maxn<<2]; LL lazy[maxn<<2]; void push_down(int rt) { if(lazy[rt]!=1) { sum[rt<<1]*=lazy[rt]; sum[rt<<1|1]*=lazy[rt]; sum[rt<<1]%=mod; sum[rt<<1|1]%=mod; lazy[rt<<1]*=lazy[rt]; lazy[rt<<1|1]*=lazy[rt]; lazy[rt<<1]%=mod; lazy[rt<<1|1]%=mod; lazy[rt]=1; } } void push_up(int rt) { sum[rt]=sum[rt<<1]+sum[rt<<1|1]; num[rt]=num[rt<<1]+num[rt<<1|1]; sum[rt]%=mod; } void creat(int l,int r,int rt) { num[rt]=sum[rt]=0; lazy[rt]=1; if(l!=r) { creat(lson); creat(rson); return; } } void insert(int x,int l,int r,int rt) { if(x<l||x>r)return; if(l==r&&l==x) { num[rt]++; sum[rt]=M.q_mod(2,ed[x],mod); sum[rt]=(sum[rt]*lazy[rt])%mod; return; } push_down(rt); insert(x,lson); insert(x,rson); push_up(rt); } void updata(int ll,int rr,int l,int r,int rt) { if(ll>rr)return ; if(ll>r||rr<l)return; if(ll<=l&&rr>=r) { lazy[rt]*=2; sum[rt]=sum[rt]*2%mod; return; } push_down(rt); updata(ll,rr,lson); updata(ll,rr,rson); push_up(rt); } LL query(int ll,int rr,int leap,int l,int r,int rt) { if(ll>rr)return 0; if(ll>r||rr<l)return 0; if(ll<=l&&rr>=r) { if(leap==0)return num[rt]; else return sum[rt]; } push_down(rt); return query(ll,rr,leap,lson)+query(ll,rr,leap,rson); } int main() { int n; while(~scanf("%d",&n)) { for(int i=1;i<=n;i++) { scanf("%d%d",&p[i].a,&p[i].b); } sort(p+1,p+n+1,cmp); for(int i=1;i<=n;i++) { ed[i]=p[i].a; p[i].a=i; } creat(1,n,1); sort(p+1,p+n+1); LL sum=0; for(int i=1;i<=n;i++) { int k=p[i].a; LL x=query(1,k-1,0,1,n,1); LL y=query(k+1,n,1,1,n,1); LL now=M.q_mod(3,p[i].b,mod); LL ps=((M.q_mod(2,ed[k],mod))*(M.q_mod(2,x,mod)))%mod; sum+=now*((ps+y)%mod)%mod; insert(k,1,n,1); updata(k+1,n,1,n,1); sum=sum%mod; } cout<<sum<<endl; } return 0; }
1005:Parenthese sequence
我的做法好像不是正经做法。。。sad
首先对于每一个)进行匹配(,如果匹配不到(,就匹配最前面的?,如果无法匹配,那就肯定无解。
一遍匹配之后,还剩下(还有?。
把每一个剩下的(匹配最后面的?;如果匹配不到?,肯定无解。
假如现在剩下x个?;
如果x是奇数,肯定无解。
如果x为0,肯定唯一解。
如果x>2,肯定多解。
如果x=2,那就把第一个?置为),第二个?置为(,如果可信,那就多解,否则,唯一解。
#include <iostream> #include<stdio.h> #include<vector> #include<queue> #include<stack> #include<string.h> #include<algorithm> #include<map> using namespace std; #define LL long long #define gcd(a,b) (b==0?a:gcd(b,a%b)) #define lcm(a,b) (a*b/gcd(a,b)) int pre[1100000]; int next[1100000]; char str[1100000]; stack<int>st; stack<int>we; int biao[1100000]; int fbiao[1100000]; int main() { while(~scanf("%s",str)) { while(!st.empty())st.pop(); while(!we.empty())we.pop(); memset(pre,-1,sizeof(pre)); memset(next,-1,sizeof(next)); int len=strlen(str); int last=-1; int leap=0; int sts=-1; for(int i=0;i<len;i++) { if(str[i]=='(') { st.push(i); } else if(str[i]==')') { if(st.empty()) { leap=1; if(sts==-1) { leap=-1; break; } else { str[sts]='('; sts=next[sts]; if(sts==-1) { pre[sts]=-1; sts=last=-1; } else pre[sts]=-1; } } else { int x=st.top(); st.pop(); } } else if(str[i]=='?') { pre[i]=last; if(sts==-1)sts=i; else next[last]=i; last=i; // cout<<sts<<endl; } } if(leap==-1) { cout<<"None"<<endl; continue; } while(!st.empty()) { if(last==-1) { break; } int x=st.top(); if(x<last) { st.pop(); str[last]=')'; last=pre[last]; } else break; } int ss=0; while(last!=-1) { last=pre[last]; ss++; } // cout<<ss<<endl; if(leap==-1||!st.empty()||ss%2) { cout<<"None"<<endl; continue; } if(ss>2) { cout<<"Many"<<endl; continue; } if(ss==0) { cout<<"Unique"<<endl; continue; } while(!st.empty())st.pop(); int lp=0; leap=1; // cout<<str<<endl; for(int i=0;i<len;i++) { if(str[i]=='?') { if(lp==0) { str[i]=')'; lp++; } else str[i]='('; } } // cout<<str<<endl; int i; for(i=0;i<len;i++) { if(str[i]=='(')st.push(i); else if(str[i]==')') { if(st.empty())break; else st.pop(); } } if(i<len)cout<<"Unique"<<endl; else cout<<"Many"<<endl; } return 0; }
1009:Exclusive or
因为结果是一些数的异或和。
我们就可以枚举每一位为1时,是由哪些数异或得来的。
对于当前位,如果A,B异或结果为1,那么A,B这两个数的当前位一个为1,一个为0,共有两种情况。
已知A+B=n。
那么对于当前位之前的数的和可以求出x种情况,对于当前位之后的数的和可以求出有y种情况。
那么总过有x*y*2种情况。
又因为A,B都是非0的,所以还需要减去0的情况。
又因为是大数。。。所以要用java,大数用C++太费劲了。。
import java.util.Scanner; import java.math.*; public class Main { public static void main(String[] args) { Scanner cin = new Scanner(System.in); BigInteger n,m,sum,zero,one,two,x,k,y,ta,tb,z; BigInteger bit[] = new BigInteger[3300]; bit[0] = BigInteger.valueOf(1); int i; for(i = 1;i <= 3000;i ++) bit[i] = bit[i-1].multiply(BigInteger.valueOf(2)); zero = BigInteger.valueOf(0); one = BigInteger.valueOf(1); two = BigInteger.valueOf(2); while(cin.hasNext()) { n = cin.nextBigInteger(); m = n; sum = BigInteger.valueOf(0); for(i = 1;;i ++) { n = m.subtract(bit[i-1]); if(n.compareTo(zero) == -1) break; x=n.divide(bit[i]).add(one); k=n.mod(bit[i]); if(bit[i-1].subtract(one).compareTo(k) == -1) ta = bit[i-1].subtract(one); else ta = k; if(zero.compareTo(k.subtract(bit[i-1]).add(one)) == 1) tb = zero; else tb = k.subtract(bit[i-1]).add(one); y=ta.subtract(tb).add(one); sum = sum.add(x.multiply(y).multiply(two).multiply(bit[i-1])); z = m.divide(bit[i]); k = m.divide(bit[i-1]); z = z.multiply(two); if(k.compareTo(z) != 0) { sum = sum.subtract(bit[i-1].multiply(two)); } } System.out.println(sum); } } }
1010:Matrix multiplication
瞎搞题,把所有的0都去掉,然后就可以了。。。
理论时间复杂度为800*800*800*(2/3)*(2/3)
#include <iostream> #include<stdio.h> #include<vector> #include<queue> #include<stack> #include<string.h> #include<algorithm> #include<map> using namespace std; #define LL long long #define gcd(a,b) (b==0?a:gcd(b,a%b)) #define lcm(a,b) (a*b/gcd(a,b)) //O(n)求素数,1-n的欧拉数 #define N 100010 //A^x = A^(x % Phi(C) + Phi(C)) (mod C) int a[880][880]; int b[880][880]; int aa[880][880]; int bb[880][880]; int c[880][880]; int main() { int n; while(~scanf("%d",&n)) { memset(a,0,sizeof(a)); memset(b,0,sizeof(b)); memset(aa,0,sizeof(aa)); memset(bb,0,sizeof(bb)); memset(c,0,sizeof(c)); for(int i=1;i<=n;i++) { for(int j=1;j<=n;j++) { scanf("%d",&a[i][j]); a[i][j]%=3; } } for(int i=1;i<=n;i++) { for(int j=1;j<=n;j++) { scanf("%d",&b[i][j]); b[i][j]%=3; } } for(int i=1;i<=n;i++) { int x=-1; for(int j=n;j>=0;j--) { aa[i][j]=x; if(a[i][j])x=j; } } for(int i=1;i<=n;i++) { int x=-1; for(int j=n;j>=0;j--) { bb[i][j]=x; if(b[i][j])x=j; } } for(int i=1;i<=n;i++) { for(int j=aa[i][0];j!=-1;j=aa[i][j]) { for(int k=bb[j][0];k!=-1;k=bb[j][k]) c[i][k]+=a[i][j]*b[j][k]; } } for(int i=1;i<=n;i++) { for(int j=1;j<=n;j++) { printf("%d",c[i][j]%3); if(j!=n)printf(" "); else printf("\n"); } } } return 0; }
2014多校联合-第五场