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;
}