zoukankan      html  css  js  c++  java
  • XVII Open Cup named after E.V. Pankratiev. Eastern GP, Division 1

    A. Count The Ones

    $ans=b-c+1$。

    #include <stdio.h>
    using namespace std ;
    
    int a  , b , c ;
    
    void solve () {
    	printf ( "%d
    " , 1 + b - c ) ;
    }
    
    int main () {
    	while ( ~scanf ( "%d%d%d" , &a , &b , &c ) ) solve () ;
    	return 0 ;
    }
    

      

    B. Craters

    求出凸包,然后枚举凸包上两个点,对第三个点旋转卡壳。因为随机数据凸包期望点数为$O(sqrt{n})$,故时间复杂度为$O(nlog n)$。

    #include<cstdio>
    #include<cmath>
    #include<algorithm>
    #include<set>
    using namespace std;
    typedef long long ll;
    typedef pair<int,int>PI;
    const int N=200010;
    int n,m,_,i,j,k,x,y;
    set<PI>T;
    ll ans=-1;
    struct P{
      int x,y;
      P(){}
      P(int _x,int _y){x=_x,y=_y;}
      P operator-(P b){return P(x-b.x,y-b.y);}
      bool operator<(const P&p)const{
        if(x!=p.x)return x<p.x;
        return y<p.y;
      }
      void write(){
        printf("%d %d
    ",x,y);
      }
    }a[N],b[N<<1],ans0,ans1,ans2;
    inline ll cross(P a,P b){
      return 1LL*a.x*b.y-1LL*a.y*b.x;
    }
    inline ll vect(P p,P p1,P p2){
      return 1LL*(p1.x-p.x)*(p2.y-p.y)-1LL*(p1.y-p.y)*(p2.x-p.x);
    }
    int convexhull(P*p,int n,P*q){
      int i,k,m;
      sort(p,p+n);
      m=0;
      for(i=0;i<n;q[m++]=p[i++])while(m>1&&vect(q[m-2],q[m-1],p[i])<=0)m--;
      k=m;
      for(i=n-2;i>=0;q[m++]=p[i--])while(m>k&&vect(q[m-2],q[m-1],p[i])<=0)m--;
      return --m;
    }
    inline void work(P a,P b,P c){
      ll now=cross(a,b)+cross(b,c)+cross(c,a);
      if(now<0)now=-now;
      if(now>ans)ans=now,ans0=a,ans1=b,ans2=c;
    }
    inline ll area(P a,P b,P c){
      ll now=cross(a,b)+cross(b,c)+cross(c,a);
      if(now<0)now=-now;
      return now;
    }
    int main(){
      scanf("%d",&n);
      if(n<200){
        for(i=0;i<n;i++)scanf("%d%d",&a[i].x,&a[i].y);
        for(i=0;i<n;i++)for(j=0;j<i;j++)for(k=0;k<j;k++){
          work(a[i],a[j],a[k]);
        }
        ans0.write();
        ans1.write();
        ans2.write();
        return 0;
      }
      _=n;
      n=0;
      while(_--){
        scanf("%d%d",&x,&y);
        if(T.find(PI(x,y))!=T.end())continue;
        a[n++]=P(x,y);
        T.insert(PI(x,y));
      }
      m=convexhull(a,n,b);
      for(i=0;i<m;i++)b[i+m]=b[i];
      for(i=0;i<m;i++){
        for(j=i+1,k=j+1;j<i+m;j++){
          if(k<=j)k=j+1;
          while(k+1<i+m&&area(b[i],b[j],b[k])<=area(b[i],b[j],b[k+1]))k++;
          work(b[i],b[j],b[k]);
        }
      }
      ans0.write();
      ans1.write();
      ans2.write();
    }
    

      

    C. MSTrikes back!

    记录最后$5$个点连通性的最小表示然后DP,注意到边权的周期不会太大,所以可以直接跳过完整的周期。

    #include<stdio.h>
    #include<algorithm>
    #include<math.h>
    #include<string.h>
    #include<string>
    #include<vector>
    #include<set>
    #include<map>
    #include<queue>
    #include<time.h>
    #include<assert.h>
    #include<iostream>
    using namespace std;
    typedef long long LL;
    typedef pair<int,int>pi;
    const int Ms=3125;
    const LL Inf=1LL<<60;
    const int LIM=100;
    int n,seed;
    LL in[LIM+1];
    LL f[LIM+1][Ms];
    LL dp[2][Ms];
    void init(int cs,LL val){
    	for(int i=0;i<Ms;i++)dp[cs][i]=val;
    }
    int g[Ms][(1<<5)+1];
    void decode(int mask,int *a){
    	for(int i=0;i<5;i++){
    		a[i]=mask%5;
    		mask/=5;
    	}
    }
    void zuixiao(int *a){
    	int dui[10];
    	memset(dui,-1,sizeof dui);
    	int cur=0;
    	for(int i=0;i<5;i++){
    		int x=a[i];
    		if(dui[x]<0){
    			dui[x]=cur++;
    		}
    		a[i]=dui[x];
    	}
    }
    int encode(int *a){
    	int res=0,tmp=1;
    	for(int i=0;i<5;i++,tmp=tmp*5){
    		res+=a[i]*tmp;
    	}
    	return res;
    }
    bool testt(int *a){
    	int b[10];
    	for(int i=0;i<5;i++)b[i]=a[i];
    	zuixiao(b);
    	for(int i=0;i<5;i++)if(b[i]!=a[i])return 0;
    	return 1;
    }
    void pre(){
    	int a[10],b[10];
    	for(int mask=0;mask<Ms;mask++){
    		decode(mask,a);
    		if(!testt(a)){
    			for(int j=0;j<1<<5;j++)g[mask][j]=-1;
    			continue;
    		}
    		//for(int i=0;i<5;i++)printf("%d ",a[i]);puts(":
    ");
    		for(int j=0;j<1<<5;j++){
    			for(int i=0;i<5;i++)b[i]=a[i];
    			b[5]=6;
    			for(int k=0;k<5;k++){
    				if(j>>k&1){
    					for(int t=0;t<5;t++){
    						if(t==k)continue;
    						if(b[t]==b[k])b[t]=b[5];
    					}
    					b[k]=b[5];
    				}
    			}
    			bool flag=0;
    			for(int k=1;k<=5;k++)if(b[0]==b[k]){flag=1;break;}
    			if(!flag)g[mask][j]=-1;
    			else{
    				for(int k=0;k<5;k++)b[k]=b[k+1];
    				zuixiao(b);
    				//for(int k=0;k<5;k++)printf("%d ",b[k]);puts("");
    				g[mask][j]=encode(b);
    			}
    		}
    	}
    }
    void upd(LL &x,LL y){if(x>y)x=y;}
    int main(){
    	pre();
    	int _;scanf("%d",&_);
    	while(_--){
    		scanf("%d%d",&n,&seed);
    		int cs=0;
    		init(cs,Inf);
    		dp[cs][0]=0;
    		for(int i=2;i<=n&&i<=LIM;i++){
    			init(cs^1,Inf);
    			seed=seed*907%2333333;
    			LL bq[10];
    			int T=seed;
    			in[i]=T;
    			for(int j=0;j<5;j++){
    				if(i-(5-j)<1)bq[j]=Inf;
    				else {
    					seed=seed*907%2333333;
    					bq[j]=seed^T;
    				}
    			}
    			for(int mask=0;mask<Ms;mask++){
    				LL w=dp[cs][mask];
    				if(w==Inf)continue;
    				for(int j=0;j<1<<5;j++){
    					if(g[mask][j]<0)continue;
    					bool flag=1;
    					for(int k=0;k<5;k++)if((j>>k&1)&&(bq[k]==Inf)){
    						flag=0;continue;
    					}
    					if(!flag)continue;
    					LL nw=w;
    					for(int k=0;k<5;k++){
    						if(j>>k&1)nw+=bq[k];
    					}
    					upd(dp[cs^1][g[mask][j]],nw);
    				}
    			}
    			cs^=1;
    			for(int j=0;j<Ms;j++)f[i][j]=dp[cs][j];
    		}
    		if(n<=LIM)printf("%lld
    ",dp[cs][0]);
    		else{
    			LL pace,pacew;
    			for(int i=LIM-1;;i--)if(in[i]==in[LIM]){
    				pace=LIM-i;
    				break;
    			}
    			int st=(n-LIM)/pace*pace+LIM;
    			//printf("st=%d
    ",st);
    			for(int i=0;i<Ms;i++){
    				dp[cs][i]=f[LIM][i]+1LL*(n-LIM)/pace*(f[LIM][i]-f[LIM-pace][i]);
    			}
    			for(int i=st+1;i<=n;i++){
    				init(cs^1,Inf);
    				seed=seed*907%2333333;
    				LL bq[10];
    				int T=seed;
    				for(int j=0;j<5;j++){
    					if(i-(5-j)<1)bq[j]=Inf;
    					else {
    						seed=seed*907%2333333;
    						bq[j]=seed^T;
    					}
    				}
    				for(int mask=0;mask<Ms;mask++){
    					LL w=dp[cs][mask];
    					if(w==Inf)continue;
    					for(int j=0;j<1<<5;j++){
    						if(g[mask][j]<0)continue;
    						bool flag=1;
    						for(int k=0;k<5;k++)if((j>>k&1)&&(bq[k]==Inf)){
    							flag=0;continue;
    						}
    						if(!flag)continue;
    						LL nw=w;
    						for(int k=0;k<5;k++){
    							if(j>>k&1)nw+=bq[k];
    						}
    						upd(dp[cs^1][g[mask][j]],nw);
    					}
    				}
    				cs^=1;
    			}
    			printf("%lld
    ",dp[cs][0]);
    		}
    	}	
    	return 0;
    }
    

      

    D. Skyscrapers

    首先用set维护所有已经被摧毁的建筑。然后用线段树维护区间内最容易被向左/向右的冲击波击毁的建筑即可。时间复杂度$O(nlog n)$。

    #include<cstdio>
    #include<set>
    #include<algorithm>
    using namespace std;
    const int N=100010,M=262150;
    int n,m,i,x,ans,f[N],g[N];
    set<int>T;
    int vl[M],vr[M],pos[N],p;
    inline int mergel(int x,int y){
      if(!x||!y)return x+y;
      return f[x]>f[y]?x:y;
    }
    inline int merger(int x,int y){
      if(!x||!y)return x+y;
      return g[x]<g[y]?x:y;
    }
    void build(int x,int a,int b){
      if(a==b){
        pos[a]=x;
        vl[x]=vr[x]=a;
        return;
      }
      int mid=(a+b)>>1;
      build(x<<1,a,mid);
      build(x<<1|1,mid+1,b);
      vl[x]=mergel(vl[x<<1],vl[x<<1|1]);
      vr[x]=merger(vr[x<<1],vr[x<<1|1]);
    }
    void askl(int x,int a,int b,int c,int d){
      if(c<=a&&b<=d){
        p=mergel(p,vl[x]);
        return;
      }
      int mid=(a+b)>>1;
      if(c<=mid)askl(x<<1,a,mid,c,d);
      if(d>mid)askl(x<<1|1,mid+1,b,c,d);
    }
    void askr(int x,int a,int b,int c,int d){
      if(c<=a&&b<=d){
        p=merger(p,vr[x]);
        return;
      }
      int mid=(a+b)>>1;
      if(c<=mid)askr(x<<1,a,mid,c,d);
      if(d>mid)askr(x<<1|1,mid+1,b,c,d);
    }
    inline void kill(int x){
      ans++;
      T.insert(x);
      x=pos[x];
      vl[x]=vr[x]=0;
      for(x>>=1;x;x>>=1){
        vl[x]=mergel(vl[x<<1],vl[x<<1|1]);
        vr[x]=merger(vr[x<<1],vr[x<<1|1]);
      }
    }
    inline void workl(int l,int r,int t){
      if(l>r)return;
      while(1){
        p=0;
        askl(1,1,n,l,r);
        if(!p)return;
        if(f[p]<t)return;
        kill(p);
      }
    }
    inline void workr(int l,int r,int t){
      if(l>r)return;
      while(1){
        p=0;
        askr(1,1,n,l,r);
        if(!p)return;
        if(g[p]>t)return;
        kill(p);
      }
    }
    int main(){
      scanf("%d",&n);
      for(i=1;i<=n;i++)scanf("%d",&x),f[i]=i-x,g[i]=i+x;
      T.insert(0);
      T.insert(n+1);
      build(1,1,n);
      scanf("%d",&m);
      while(m--){
        scanf("%d",&x);
        ans=0;
        kill(x);
        set<int>::iterator j=T.find(x),k;
        k=j;
        j--;k++;
        workl(*j+1,x-1,f[x]);
        workr(x+1,*k-1,g[x]);
        printf("%d
    ",ans);
      }
    /*
    left:
    a[x]-a[y]>=x-y
    y-a[y]>=x-a[x]
    get max(y-a[y])
    right:
    a[x]-a[y]>=y-x
    y+a[y]<=x+a[x]
    get min(y+a[y])
    */
    }
    

      

    E. Blackboard

    按题意模拟即可。

    #include<stdio.h>
    #include<algorithm>
    #include<math.h>
    #include<string.h>
    #include<string>
    #include<vector>
    #include<set>
    #include<map>
    #include<queue>
    #include<time.h>
    #include<assert.h>
    #include<iostream>
    using namespace std;
    typedef long long LL;
    typedef pair<int,int>pi;
    int n,ty;
    int a[103][103];
    void rev(){
    	for(int i=1;i<=n;i++){
    		for(int j=i;j<=n;j++){
    			swap(a[i][j],a[j][i]);
    		}
    	}
    }
    void solve1(){
    	int cur=1;
    	for(int i=1;i<=n;i++){
    		if(i&1){
    			for(int j=1;j<=n;j++){
    				a[i][j]=cur++;
    			}
    		}
    		else{
    			for(int j=n;j>=1;j--){
    				a[i][j]=cur++;
    			}
    		}
    	}
    }
    bool isok(int x,int y){
    	return x>=1&&x<=n&&y>=1&&y<=n&&a[x][y]==0;
    }
    int di[4][2]={{0,1},{1,0},{0,-1},{-1,0}};
    void solve2(){
    	int d=0;
    	int sx=1,sy=1;
    	memset(a,0,sizeof a);
    	int cur=1;
    	for(int it=1;it<=n*n;it++){
    		a[sx][sy]=cur++;
    		int nx=sx+di[d][0],ny=sy+di[d][1];
    		if(it==n*n)break;
    		while(!isok(nx,ny)){
    			d++;
    			d%=4;
    			nx=sx+di[d][0],ny=sy+di[d][1];
    		}
    		sx=nx,sy=ny;
    	}
    }
    int main(){
    	while(scanf("%d%d",&n,&ty)!=EOF){
    		if(ty==1||ty==2)solve1();
    		if(ty==3||ty==4)solve2();
    		if(ty==2||ty==4)rev();
    		for(int i=1;i<=n;i++){
    			for(int j=1;j<=n;j++){
    				printf("%d%c",a[i][j],j==n?'
    ':' ');
    			}
    		}
    	}
    	return 0;
    }
    

      

    F. Buddy Numbers

    若质数太多那么显然无解,对于小数据爆搜即可。

    #include <bits/stdc++.h>
    using namespace std ;
    
    int a[1000] , n ;
    
    void solve () {
    	if ( n == 1 ) {
    		printf ( "1
    " ) ;
    		return ;
    	}
    	if ( n == 2 ) {
    		printf ( "1 2
    " ) ;
    		return ;
    	}
    	if ( n == 3 ) {
    		printf ( "2 1 3
    " ) ;
    		return ;
    	}
    	if ( n == 4 ) {
    		printf ( "2 4 1 3
    " ) ;
    		return ;
    	}
    	if ( n == 6 ) {
    		printf ( "3 6 2 4 1 5
    " ) ;
    		return ;
    	}
    	printf ( "-1
    " ) ;
    		
    }
    
    int main () {
    	while ( ~scanf ( "%d" , &n ) ) solve () ;
    	return 0 ;
    }
    

      

    G. Gmoogle

    按题意模拟即可。注意首尾空格的处理以及文末没有标点符号的情况的处理。

    #include<stdio.h>
    #include<algorithm>
    #include<math.h>
    #include<string.h>
    #include<string>
    #include<vector>
    #include<set>
    #include<map>
    #include<queue>
    #include<time.h>
    #include<assert.h>
    #include<sstream>
    #include<iostream>
    using namespace std;
    typedef long long LL;
    typedef pair<int,int>pi;
    string s;
    vector<string>jz;
    int can[1020];
    int isend(int loc){
    	if(s[loc]!='.'&&s[loc]!='!'&&s[loc]!='?')return 0;
    	if(s[loc]=='.'){
    		int j=loc+1;
    		while(j<s.size()&&s[j]==' ')j++;
    		if(j<s.size()&&s[j]>='a'&&s[j]<='z')return 0;
    	}
    	return 1;
    }
    void cg(char &c){if(c>='A'&&c<='Z')c=c-'A'+'a';}
    bool cmp(char c1,char c2){
    	cg(c1),cg(c2);
    	if(c1==c2)return 1;
    	return 0;
    }
    bool ok(string &wb,string& in){
    	for(int i=0;i+in.size()<=wb.size();i++)if(isalpha(wb[i])){
    		bool flag=1;
    		if(i&&isalpha(wb[i-1]))continue;//
    		int j=i+in.size();
    		if(j<wb.size()&&isalpha(wb[j]))continue;//
    		//while ( j < wb.size () && wb[j] == ' ' ) ++ j ;
    		//if(j<wb.size()-1&&wb[j]=='.')continue;
    		for(int j=0;j<in.size();j++){
    			if(cmp(wb[i+j],in[j])!=1){flag=0;break;}
    		}
    		if(flag)return 1;
    	}
    	return 0;
    }
    bool zhu(char x){
      if(x>='a'&&x<='z')return 1;
      if(x>='A'&&x<='Z')return 1;
      if(x==' ')return 1;
      if(x>='0'&&x<='9')return 1;
      if(x=='.'||x=='?'||x=='!')return 1;
      return 0;
    }
    void fix ( string& s ) {
    	while ( !zhu(s[s.size () - 1]) ) s.pop_back () ;
    }
    int main(){
    	getline(cin,s);
    	fix ( s ) ;
    	int k = 0 ;
    	for(int l=0;l<s.size();){
    		while(l<s.size()&&s[l]==' ')l++;
    		if(l>=s.size())break;
    		//if ( s[l] == '.' /*|| s[l] == '?' || s[k] == '!'*/ ) while ( 1 ) ;
    		int r=l;
    		string tmp="";
    		while(r<s.size()&&!isend(r))tmp.push_back(s[r++]);
    		if ( r < s.size () ) tmp.push_back(s[r++]);
    		while(tmp[tmp.size()-1]==' ')tmp.pop_back();
    		//printf ( "%d
    " , ( int ) tmp.size () ) ;
    		jz.push_back(tmp);
    		l=r;
    	}
    	/*
    	cout<<"OUTPUT"<<endl;
    	for(int i=0;i<jz.size();i++)cout<<jz[i]<<endl;
    	*/
    	int q;scanf("%d",&q);
    	string rub;
    	getline(cin,rub);
    	while(q--){
    		string que;
    		getline(cin,que);
    		fix ( que ) ;
    		for(int i=0;i<jz.size();i++)can[i]=1;
    		stringstream ss(que);
    		string tmp;
    		while(ss>>tmp){
    			fix ( tmp ) ;
    			for(int i=0;i<jz.size();i++){
    				if(!ok(jz[i],tmp))can[i]=0;
    			}
    		}
    		int i=0,j=que.size()-1;
    		while(que[i]==' ')i++;
    		while(que[j]==' ')j--;
    		cout<<"Search results for "";
    		for(int it=i;it<=j;it++)printf("%c",que[it]);
    		cout<<"":
    ";
    		for(int i=0;i<jz.size();i++)if(can[i]){
    			cout<<"- ""<<jz[i]<<""
    ";
    		}
    	}
    	return 0;
    }
    

      

    H. Generator

    线性筛求出每个数的最小质因子即可。

    #include<stdio.h>
    #include<algorithm>
    #include<math.h>
    #include<string.h>
    #include<string>
    #include<vector>
    #include<set>
    #include<map>
    #include<queue>
    #include<time.h>
    #include<assert.h>
    #include<iostream>
    using namespace std;
    typedef long long LL;
    typedef pair<int,int>pi;
    LL n;
    LL sum[10000020];
    int tot[10000020];
    bool isp[10000200];
    vector<int>pri;
    const int Maxn=10000010;
    int getsq(int x){
    	int tmp=sqrt(x+0.5);
    	while(tmp*tmp<x)tmp++;
    	while(tmp*tmp>x)tmp--;
    	return tmp-1;
    }
    void pre(){
    	for(int i=2;i<Maxn;i++){
    		if(!isp[i])pri.push_back(i),sum[i]=getsq(i);
    		for(int j=0;j<pri.size();j++){
    			int x=pri[j];
    			if(x*i>=Maxn)break;
    			sum[x*i]=x-1;
    			isp[i*x]=1;
    			if(i%x==0)break;
    		}
    	}
    	//for(int i=2;i<=10;i++)printf("%lld ",sum[i]);puts("");
    	for(int i=2;i<Maxn;i++)sum[i]+=sum[i-1];
    	for(int i=2;i<Maxn;i++)tot[i]=tot[i-1]+(!isp[i]);
    }
    int main(){
    	pre();
    	int _;scanf("%d",&_);
    	while(_--){
    		scanf("%lld",&n);
    		LL ans=sum[n];
    		if(ans==0)printf("0/1
    ");
    		else{
    			LL gc=__gcd((LL)tot[n],ans);
    			printf("%lld/%lld
    ",ans/gc,tot[n]/gc);
    		}		
    	}
    	return 0;
    }
    

      

    I. Addition

    维护二进制字典树即可。

    #include <bits/stdc++.h>
    using namespace std ;
    
    typedef long long LL ;
    
    const int MAXN = 100005 ;
    
    int nxt[MAXN][2] ;
    int cnt[MAXN] ;
    char s[MAXN] , s1[MAXN] ;
    int cur , root ;
    int n , m ;
    
    int newnode () {
    	++ cur ;
    	nxt[cur][0] = nxt[cur][1] = 0 ;
    	cnt[cur] = 0 ;
    	return cur ;
    }
    
    void insert ( char s[] ) {
    	int now = root ;
    	for ( int i = 0 ; i < m ; ++ i ) {
    		int x = s[i] ;
    		if ( !nxt[now][x] ) nxt[now][x] = newnode () ;
    		now = nxt[now][x] ;
    		cnt[now] ++ ;
    	}
    }
    
    int query ( char s[] ) {
    	int now = root , ans = 0 ;
    	for ( int i = 0 ; i < m ; ++ i ) {
    		int x = s[i] ;
    		if ( !x ) ans += cnt[nxt[now][1]] ;
    		now = nxt[now][x] ;
    	}
    	return ans ;
    }
    
    void solve () {
    	cur = 0 ;
    	root = newnode () ;
    	for ( int i = 1 ; i <= n ; ++ i ) {
    		scanf ( "%s" , s ) ;
    		for ( int j = 0 ; j < m ; ++ j ) {
    			s[j] -= '0' ;
    			s1[j] = 1 ^ s[j] ;
    		}
    		int ans = query ( s1 ) ;
    		insert ( s ) ;
    		printf ( "%d
    " , ans ) ;
    		fflush ( stdout ) ;
    	}
    }
    
    int main () {
    	scanf ( "%d%d" , &n , &m ) ;
    	solve () ;
    	return 0 ;
    }
    

      

    J. Votter and Paul De Mort

    留坑。

    K. GCD on the segments

    考虑枚举左端点$i$,则随着右端点的右移,一共只有$O(log n)$种不同的$gcd$取值。所以首先通过ST表+二分查找预处理出$O(nlog n)$个四元组$(x,i,l,r)$,表示左端点为$i$,右端点取值范围在$[l,r]$内,且这一段的$gcd$都为$x$。

    将四元组按照$x$为第一关键字,$i$为第二关键字排序,对于相同的$x$一起处理。

    当$x$相同时,显然所有的$i$互不相同。设$f[i]$为恰好以位置$i$为结尾的最优解,则对于一个四元组$(x,i,l,r)$,能更新它的最优解为区间$[1,i-1]$的最优值$+1$,然后用它更新区间$[l,r]$的$f[]$。用支持打标记的线段树维护即可。时间复杂度$O(nlog^2n)$。

    #include<cstdio>
    #include<cstdlib>
    #include<algorithm>
    using namespace std;
    const int N=100010,K=17,P=1000000007,M=262145;
    int T,n,m,i,j,x,y,l,r,mid,Log[N],val,f[K][N];
    struct PI{
      int x,i,l,r;
      PI(){}
      PI(int _x,int _i,int _l,int _r){x=_x,i=_i,l=_l,r=_r;}
    }a[3000000];
    inline bool cmp(PI a,PI b){return a.x==b.x?a.i<b.i:a.x<b.x;}
    struct Num{
      int x,y;
      Num(){x=y=0;}
      Num(int _x,int _y){x=_x,y=_y;}
      inline Num operator+(Num b){
        if(x<b.x)return b;
        if(x>b.x)return Num(x,y);
        return Num(x,(y+b.y)%P);
      }
      inline Num operator+(int _x){return Num(x+_x,y);}
      inline Num operator-(int b){return Num(x,(long long)y*b%P);}
      inline void operator+=(Num b){*this=*this+b;}
    }tmp,v[M],tag[M],ans;
    int pos[M];
    inline void read(int&a){char c;while(!(((c=getchar())>='0')&&(c<='9')));a=c-'0';while(((c=getchar())>='0')&&(c<='9'))(a*=10LL)+=c-'0';}
    inline int askgcd(int y){int k=Log[y-i+1];return __gcd(f[k][i],f[k][y-(1<<k)+1]);}
    inline void clean(int x){
      if(pos[x]<T)pos[x]=T,v[x]=tag[x]=Num();
    }
    inline void tag1(int x,Num y){
      clean(x);
      v[x]+=y;
      tag[x]+=y;
    }
    inline void pb(int x){
      if(tag[x].x){
        tag1(x<<1,tag[x]);
        tag1(x<<1|1,tag[x]);
        tag[x]=Num();
      }
    }
    inline void up(int x){
      clean(x<<1),clean(x<<1|1);
      v[x]=v[x<<1]+v[x<<1|1];
    }
    void change(int x,int a,int b,int c,int d){
      clean(x);
      if(c<=a&&b<=d){tag1(x,tmp);return;}
      pb(x);
      int mid=(a+b)>>1;
      if(c<=mid)change(x<<1,a,mid,c,d);
      if(d>mid)change(x<<1|1,mid+1,b,c,d);
      up(x);
    }
    void ask(int x,int a,int b,int c,int d){
      clean(x);
      if(c<=a&&b<=d){tmp+=v[x];return;}
      pb(x);
      int mid=(a+b)>>1;
      if(c<=mid)ask(x<<1,a,mid,c,d);
      if(d>mid)ask(x<<1|1,mid+1,b,c,d);
      up(x);
    }
    int main(){
      for(i=2;i<=100000;i++)Log[i]=Log[i>>1]+1;
      while(~scanf("%d",&n)){
        m=0;
        ans=Num();
        for(i=1;i<=n;i++)read(f[0][i]);
        int flag=0;
        for(i=2;i<=n;i++)if(f[0][i]!=f[0][i-1]){flag=1;break;}
        if(!flag){printf("%d 1
    ",n);continue;}
        for(j=1;j<K;j++)for(i=1;i+(1<<j-1)<=n;i++)f[j][i]=__gcd(f[j-1][i],f[j-1][i+(1<<j-1)]);
        for(i=1;i<=n;i++)for(x=i;x<=n;x=y+1){
          val=askgcd(y=x),l=x+1,r=n;
          while(l<=r)if(askgcd(mid=(l+r)>>1)==val)l=(y=mid)+1;else r=mid-1;
          a[++m]=PI(val,i,x,y);
        }
        sort(a+1,a+m+1,cmp);
        for(i=1;i<=m;i++){
          if(i==1||a[i].x!=a[i-1].x)T++;
          tmp=Num();
          if(a[i].i>1)ask(1,1,n,1,a[i].i-1);
          if(!tmp.x)tmp=Num(1,1);else tmp.x++;
          ans+=tmp-(a[i].r-a[i].l+1);
          change(1,1,n,a[i].l,a[i].r);
        }
        printf("%d %d
    ",ans.x,ans.y);
      }
      return 0;
    }
    

      

    L. Fibonacci Equation

    分类讨论。

    #include<stdio.h>
    #include<algorithm>
    #include<math.h>
    #include<string.h>
    #include<string>
    #include<vector>
    #include<set>
    #include<map>
    #include<queue>
    #include<time.h>
    #include<assert.h>
    #include<iostream>
    using namespace std;
    typedef long long LL;
    typedef pair<int,int>pi;
    LL a[100];
    LL x,y,z;
    int main(){
    	/*
    	a[0]=0,a[1]=1;
    	for(int i=2;i<=30;i++)a[i]=a[i-1]+a[i-2];
    	for(int i=1;i<=25;i++){
    		printf("%lld %lld
    ",a[i],a[i]*a[i]-4*a[i-1]*a[i+1]);
    	}
    	*/
    	while(scanf("%lld%lld%lld",&x,&y,&z)!=EOF){
    		if(x==0){printf("1
    ");continue;}
    		if(y>x&&y>z){
    			if(y==3)printf("1
    ");
    			else printf("2
    ");
    		}
    		if(y<x&&y<z)printf("0
    ");
    		if(y>min(x,z)&&y<max(x,z)){
    			if(y==1)printf("2
    ");
    			else printf("0
    ");
    		}
    		//printf("real=%lld
    ",a[y]*a[y]-4*a[x]*a[z]);
    	}
    	return 0;
    }
    

      

  • 相关阅读:
    Python学习札记(十五) 高级特性1 切片
    LeetCode Longest Substring Without Repeating Characters
    Python学习札记(十四) Function4 递归函数 & Hanoi Tower
    single number和变体
    tusen 刷题
    实验室网站
    leetcode 76. Minimum Window Substring
    leetcode 4. Median of Two Sorted Arrays
    leetcode 200. Number of Islands 、694 Number of Distinct Islands 、695. Max Area of Island 、130. Surrounded Regions 、434. Number of Islands II(lintcode) 并查集 、178. Graph Valid Tree(lintcode)
    刷题注意事项
  • 原文地址:https://www.cnblogs.com/clrs97/p/6649222.html
Copyright © 2011-2022 走看看