zoukankan      html  css  js  c++  java
  • XVIII Open Cup named after E.V. Pankratiev. Grand Prix of SPb

    A. Base $i - 1$ Notation

    两个性质:

    • $2=1100$
    • $122=0$

    利用这两条性质实现高精度加法即可。

    时间复杂度$O(n)$。

    #include<stdio.h>
    #include<iostream>
    #include<string.h>
    #include<string>
    #include<ctype.h>
    #include<math.h>
    #include<set>
    #include<map>
    #include<vector>
    #include<queue>
    #include<bitset>
    #include<algorithm>
    #include<time.h>
    using namespace std;
    const int N = 6e6 + 10;
    const int inf = 1e9;
    int casenum, casei;
    char a[N], b[N];
    int c[N];
    int main()
    {
    	freopen("base-i-1.in","r",stdin); freopen("base-i-1.out","w",stdout);
    	while(~scanf("%s%s", a, b))
    	{
    		int n = strlen(a); reverse(a, a + n);
    		int m = strlen(b); reverse(b, b + m);
    		//int n = 5e5; for(int i = 0; i < n; ++i)a[i] = '1'; a[n] = 0;
    		//int m = 5e5; for(int i = 0; i < m; ++i)b[i] = '1'; b[m] = 0;
    		int g = max(n, m);
    		for(int i = 0; i < g; ++i)
    		{
    			int p = i / 2;
    			
    			c[i] = 0;
    			if(i < n)c[i] += a[i] - 48;
    			if(i < m)c[i] += b[i] - 48;
    		}
    		for(int i = 0; i < g; ++i)
    		{
    			int t=min(c[i]/2,min(c[i+1]/2,c[i+2]));
    			c[i]-=t*2;
    			c[i+1]-=t*2;
    			c[i+2]-=t;
    			int w = c[i] / 2;
    			if(w)
    			{
    				c[i + 2] += w;
    				c[i + 3] += w;
    				g = max(g, i + 4);
    			}
    			c[i] %= 2;
    		}
    		while(g>1&&!c[g-1])g--;
    		for(int i = g - 1; i >= 0; --i)printf("%d", c[i]);
    		puts("");
    	}
    	return 0;
    }
    /*
    
    
    */
    

      

    B. Squaring a Bit

    直接暴力枚举平方数即可通过,需要手写popcount。

    #include<stdio.h>
    #include<iostream>
    #include<string.h>
    #include<string>
    #include<ctype.h>
    #include<math.h>
    #include<set>
    #include<map>
    #include<vector>
    #include<queue>
    #include<bitset>
    #include<algorithm>
    #include<time.h>
    using namespace std;
    const int N = 3e5 + 10;
    typedef long long LL;
    LL n;
    int v[65555];
    int popcount(LL x){
      return v[x&65535]+v[x>>16&65535]+v[x>>32&65535]+v[x>>48];
    }
    int main()
    {
        for(int i=1;i<65536;i++)v[i]=v[i>>1]+(i&1);
    	freopen("bit-squares.in","r",stdin); freopen("bit-squares.out","w",stdout);
    	while(~scanf("%lld", &n))
    	{
    		LL len = 0;
    		int one = 0;
    		while(n)
    		{
    			++len;
    			one += n & 1;
    			n /= 2;
    		}
    		
    		LL bott = 1ll << (len - 1);
    		int bot = sqrt(bott) + 0.99999999;
    		LL topp = (1ll << len) - 1;
    		int top = sqrt(min(topp, (LL)1e18));
    		//printf("%lld %lld
    ", bott, topp);
    		//printf("%d %d
    ", bot, top);
    		int ans = 0;
    		LL val = (LL)bot * bot, add = bot * 2 + 1;
    		int i=bot;
    		for(;i+4<=top;i+=4){
                if(popcount(val) == one)++ans;
                val += add, add += 2;
                if(popcount(val) == one)++ans;
                val += add, add += 2;
                if(popcount(val) == one)++ans;
                val += add, add += 2;
                if(popcount(val) == one)++ans;
                val += add, add += 2;
    		}
    		for(; i <= top; ++i, val += add, add += 2)
    		{
    			//printf("%d %lld
    ", i, val);
    			//val = (LL)i * i;
    			if(popcount(val) == one)++ans;
    		}
    		printf("%d
    ", ans);
    	}
    	return 0;
    }
    /*
    
    
    */
    

      

    C. Chickens

    状压DP求方案数。

    #include<stdio.h>
    #include<iostream>
    #include<string.h>
    #include<string>
    #include<ctype.h>
    #include<math.h>
    #include<set>
    #include<map>
    #include<vector>
    #include<queue>
    #include<bitset>
    #include<algorithm>
    #include<time.h>
    using namespace std;
    const int N = 3e5 + 10;
    const int inf = 1e9;
    int casenum, casei;
    int c[15], e[15];
    int f[15][1 << 13];
    int n;
    int main()
    {
    	freopen("chickens.in","r",stdin);
    	freopen("chickens.out","w",stdout);
    	while(~scanf("%d", &n))
    	{
    		for(int i = 0; i < n; ++i)scanf("%d", &c[i]);
    		for(int i = 0; i < n; ++i)scanf("%d", &e[i]);
    		memset(f, 0, sizeof(f)); f[0][0] = 1;
    		int top = (1 << n) - 1;
    		for(int i = 0; i < n; ++i)
    		{
    			for(int j = 0; j <= top; ++j)if(f[i][j])
    			{
    				for(int k = 0; k < n; ++k)if((~j >> k & 1) && c[i] <= e[k])
    				{
    					f[i + 1][j | 1 << k] += f[i][j];
    				}
    			}
    		}
    		printf("%d
    ", f[n][top]);
    	}
    	return 0;
    }
    /*
    
    
    */
    

      

    D. Lights at a Crossing

    对于每个观察,枚举两盏红灯,由剩余时间大的向小的连权值为差值的有向边,则最小周期为这个有向图的最小环。

    时间复杂度$O(n^3+mn^2)$。

    #include<cstdio>
    const int N=30,inf=10000000;
    int n,m,i,j,k,f[N][N],a[N],ans=inf;char s[99];
    inline void up(int&x,int y){x>y?(x=y):0;}
    int main(){
      scanf("%d%d",&n,&m);
      for(i=1;i<=n;i++)for(j=1;j<=n;j++)f[i][j]=inf;
      while(m--){
        for(i=1;i<=n;i++){
          scanf("%s",s);
          if(s[0]=='X')a[i]=-1;else sscanf(s,"%d",&a[i]);
        }
        for(i=1;i<=n;i++)if(~a[i])for(j=i+1;j<=n;j++)if(~a[j]){
          if(a[i]<a[j])up(f[i][j],a[j]-a[i]);
          if(a[i]>a[j])up(f[j][i],a[i]-a[j]);
        }
      }
      for(k=1;k<=n;k++)for(i=1;i<=n;i++)for(j=1;j<=n;j++)up(f[i][j],f[i][k]+f[k][j]);
      for(i=1;i<=n;i++)up(ans,f[i][i]);
      if(ans==inf)ans=-1;
      printf("%d",ans);
    }
    

      

    E. Decimal Form

    法雷序列求两分数之间分母最小的分数。

    时间复杂度$O(Tlog w)$。

    #include<cstdio>
    #include<iostream>
    #include<algorithm>
    #include<cmath>
    #include<cstring>
    using namespace std;
    typedef long long ll;
    typedef long double ld;
    typedef __int128 lll;
    typedef pair<lll,lll>P;
    lll n,r,a,b,c,d,t;
    int Case;
    ld goal;
    const int lim=1000000000;
    const ld eps=1e-15;
    lll gcd(lll a,lll b){return b?gcd(b,a%b):a;}
    P cal(lll a,lll b,lll c,lll d){
    	lll x=a/b+1;
    	if(x*d<c)return P(x,1);
    	if(!a)return P(1,d/c+1);
    	if(a<=b&&c<=d){
    		P t=cal(d,c,b,a);
    		swap(t.first,t.second);
    		return t;
    	}
    	x=a/b;
    	P t=cal(a-b*x,b,c-d*x,d);
    	t.first+=t.second*x;
    	return t;
    }
    void write(lll x){
    	if(x>=10)write(x/10);
    	x%=10;
    	printf("%d",(int)x);
    }
    //0.666666666666666667
    int main(){
    	freopen("decimal-form.in","r",stdin);
    	freopen("decimal-form.out","w",stdout);
    	scanf("%d",&Case);
    	while(Case--){
    		n=18;
    		static char s[100];
    		scanf("%s",s);
    		int len=strlen(s);
    		r=0;
    		for(int i=2;i<len;i++)r=r*10+s[i]-'0';
    		if(!r){
    			puts("0 1");
    			continue;
    		}
    		for(t=10;n--;t*=10);
    		a=r*10-5,b=t;
    		c=r*10+5,d=t;
    		lll o=gcd(a,b);
    		a/=o,b/=o;
    		o=gcd(c,d);
    		c/=o,d/=o;
    		P p=cal(a,b,c,d);
    		if(b<p.second)p=P(a,b);
    		write(p.first);
    		putchar(' ');
    		write(p.second);
    		puts("");
    	}
    }
    

      

    F. Martian Maze

    留坑。

    G. Wet Mole

    Floodfill求出所有水能灌到的点即可。

    时间复杂度$O(nm)$。

    #include<cstdio>
    const int N=1010;
    int n,m,i,j,flag;char a[N][N];bool v[N][N];
    inline bool check(int x,int y){
    	if(x<1||x>n||y<1||y>m)return 0;
    	if(a[x][y]=='#')return 0;
    	return 1;
    }
    void dfs(int x,int y){
    	if(v[x][y])return;
    	v[x][y]=1;
    	if(check(x+1,y))dfs(x+1,y);
    	else{
    		if(check(x,y-1))dfs(x,y-1);
    		if(check(x,y+1))dfs(x,y+1);
    	}
    }
    int main(){
    	freopen("mole.in","r",stdin);
    	freopen("mole.out","w",stdout);
    	scanf("%d%d",&n,&m);
    	for(i=1;i<=n;i++)scanf("%s",a[i]+1);
    	for(i=1;i<=m;i++)if(a[1][i]=='.')dfs(1,i);
    	for(i=1;i<=n;i++)for(j=1;j<=m;j++)if(a[i][j]=='.'&&!v[i][j]){
    		if(!flag){
    			flag=1;
    			a[i][j]='X';
    		}
    	}
    	if(flag){
    		puts("Yes");
    		for(i=1;i<=n;i++)puts(a[i]+1);
    	}else puts("No");
    }
    

      

    H. Oddities

    留坑。

    I. Sorting on the Plane

    将所有向量分成两类:在$1$号向量左侧和右侧的。然后分别排序即可。

    时间复杂度$O(nlog n)$。

    #include<cstdio>
    #include<algorithm>
    #include<vector>
    using namespace std;
    const int N=100010;
    int n,i,f[N],m,t;
    vector<int>q[2];
    int ask(int x,int y){
    	printf("? %d %d
    ",x,y);
    	fflush(stdout);
    	int t;
    	scanf("%d",&t);
    	return t;
    }
    bool cmp(int x,int y){return ask(x,y);}
    int main(){
    	scanf("%d",&n);
    	if(n==1){
    		puts("! YES");
    		puts("1");
    		fflush(stdout);
    		return 0;
    	}
    	for(i=2;i<=n;i++){
    		q[ask(1,i)].push_back(i);
    	}
    	for(i=0;i<2;i++)sort(q[i].begin(),q[i].end(),cmp);
    	for(i=0;i<q[0].size();i++)f[++m]=q[0][i];
    	f[++m]=1;
    	for(i=0;i<q[1].size();i++)f[++m]=q[1][i];
    	if(t=ask(f[1],f[m]))puts("! YES");else puts("! NO");
    	if(!t)printf("%d ",m);
    	for(i=1;i<=m;i++)printf("%d ",f[i]);
    	fflush(stdout);
    	return 0;
    }
    

      

    J. Center of List of Sums

    二分求出上下界以及上下界的排名,然后将中间的数暴力取出即可。

    时间复杂度$O(nlog n)$。

    #include<cstdio>
    #include<algorithm>
    using namespace std;
    typedef long long ll;
    const int N=2000010;
    int n,m,i;ll a[N],b[N],q[N],L,R,down,up,cntdown,cntup;
    inline ll cal(ll lim){//<=lim
    	int i=1,j=n;
    	ll t=0;
    	for(i=1;i<=n;i++){
    		while(j&&a[i]+b[j]>lim)j--;
    		t+=j;
    	}
    	return t;
    }
    inline ll getkth(ll k){
    	ll l=0,r=2100000000,mid,t;
    	while(l<=r){
    		mid=(l+r)>>1;
    		if(cal(mid)>=k)r=(t=mid)-1;else l=mid+1;
    	}
    	return t;
    }
    void push(ll A,ll B){
    	int i,j=n,k=n;
    	for(i=1;i<=n;i++){
    		while(j&&a[i]+b[j]>=A)j--;
    		while(k&&a[i]+b[k]>B)k--;
    		for(int o=j+1;o<=k;o++)q[++m]=a[i]+b[o];
    	}
    }
    int main(){
    	freopen("sums-center.in","r",stdin);
    	freopen("sums-center.out","w",stdout);
    	scanf("%d",&n);
    	for(i=1;i<=n;i++)scanf("%lld",&a[i]);
    	for(i=1;i<=n;i++)scanf("%lld",&b[i]);
    	sort(a+1,a+n+1);
    	sort(b+1,b+n+1);
    	L=1LL*n*(n-1)/2+1;
    	R=1LL*n*(n+1)/2;
    	down=getkth(L);
    	up=getkth(R);
    	//printf("L=%lld R=%lld down=%lld up=%lld
    ",L,R,down,up);
    	if(down==up){
    		for(ll o=L;o<=R;o++)printf("%lld ",down);
    		return 0;
    	}
    	cntdown=cal(down);//<=down
    	cntup=cal(up-1);//<up
    	//printf("cnt=%lld %lld
    ",cntdown,cntup);
    	push(down+1,up-1);
    	for(ll o=L;o<=cntdown&&o<=R;o++)q[++m]=down;
    	for(ll o=R;o>cntup&&o>=L;o--)q[++m]=up;
    	sort(q+1,q+m+1);
    	for(i=1;i<=m;i++)printf("%lld ",q[i]);
    }
    

      

    K. Cookies

    将每个串排序,然后直接DP求出最长链即可。

    #include<cstdio>
    #include<string>
    #include<algorithm>
    #include<map>
    #include<iostream>
    using namespace std;
    const int N=180000;
    int n,m,i;
    int len[N];
    int f[N],g[N];
    string name[N],show[N],need[N];
    map<string,int>pos;
    string q[N];
    int dp(int x){
    	if(!x)return 0;
    	if(f[x])return f[x];
    	int A=f[x],B=0;
    	for(int i=0;i<name[x].size();i++){
    		string now=name[x];
    		now.erase(i,1);
    		int o=pos[now];
    		if(!o)continue;
    		int t=dp(o);
    		if(t>A)A=t,B=o;
    	}
    	f[x]=A+1,g[x]=B;
    	return f[x];
    }
    int main(){
    	freopen("word-chains.in","r",stdin); freopen("word-chains.out","w",stdout);
    	cin>>n;//n=10000
    	for(i=0;i<n;i++)cin>>need[i];
    	cin>>m;//173554
    	m++;
    	name[1]="";
    	show[1]=".";
    	for(i=2;i<=m;i++){
    		cin>>name[i];
    		show[i]=name[i];
    	}
    	for(i=1;i<=m;i++){
    		sort(name[i].begin(),name[i].end());
    		pos[name[i]]=i;//sorted
    		len[i]=name[i].size();
    	}
    	for(i=0;i<n;i++){
    		string now=need[i];
    		sort(now.begin(),now.end());
    		int x=pos[now];
    		dp(x);
    		int cnt=0;
    		while(x){
    			q[++cnt]=show[x];
    			x=g[x];
    		}
    		q[1]=need[i];
    		cout<<cnt<<endl;
    		for(int j=1;j<=cnt;j++){
    			cout<<q[j];
    			if(j<cnt)cout<<" -> ";else cout<<endl;
    		}
    	}
    }
    /*
    4
    university
    open
    cup
    cookie
    17
    university
    intrusive
    neuritis
    unities
    seniti
    nisei
    sine
    sei
    e
    es
    one
    ne
    open
    cup
    up
    p
    cookie
    */
    

      

    L. Xor-fair Division

    若所有数异或和非$0$,则答案为$0$,否则答案为$2^n-2$。

    #include<cstdio>
    typedef long long ll;
    int n;long long ans,sum,x;
    int main(){
    	freopen("xorseq.in","r",stdin);
    	freopen("xorseq.out","w",stdout);
    	scanf("%d",&n);
    	ans=1LL<<n;
    	while(n--){
    		scanf("%lld",&x);
    		sum^=x;
    	}
    	if(sum)ans=0;
    	else if(n==1)ans=0;
    	else ans-=2;
    	printf("%lld",ans);
    }
    

      

  • 相关阅读:
    ACM实用C语言函数
    Java中的数组和方法
    eclipse常用快捷键
    【转载】第十章 五种对称加密算法总结
    【转载】ZooKeeper学习第二期--ZooKeeper安装配置
    【转载】Java垃圾回收机制
    【转载】JVM系列三:JVM参数设置、分析
    【转载】JVM系列二:GC策略&内存申请、对象衰老
    【转载】JVM系列一:JVM内存组成及分配
    java项目性能测试过程记录
  • 原文地址:https://www.cnblogs.com/clrs97/p/7754199.html
Copyright © 2011-2022 走看看