zoukankan      html  css  js  c++  java
  • 2017 多校联合训练 7 题解

    Problem 1002

    因为是完全K叉树

    所以这棵树的所有孩子最多只有一个不是满K叉树

    对这个孩子进行递归处理即可
    注意K=1时要特判

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 const int inf=(1<<30)-1;
     4 const int maxn=100010;
     5 #define REP(i,n) for(int i=(0);i<(n);i++)
     6 #define FOR(i,j,n) for(int i=(j);i<=(n);i++)
     7 typedef long long ll;
     8 typedef pair<int,int> PII;
     9 int IN(){
    10     int c,f,x;
    11     while (!isdigit(c=getchar())&&c!='-');c=='-'?(f=1,x=0):(f=0,x=c-'0');
    12     while (isdigit(c=getchar())) x=(x<<1)+(x<<3)+c-'0';return !f?x:-x;
    13 }
    14 #define de(x) cout << #x << "=" << x << endl
    15 #define MP make_pair
    16 #define PB push_back
    17 #define fi first
    18 #define se second
    19 ll n,k;
    20 ll sum[100],t[100];
    21 
    22 int main()
    23 {
    24     int T;scanf("%d",&T);
    25     while(T--)
    26     {
    27         scanf("%lld%lld",&n,&k);
    28         if(k==1) {
    29             if(n%4==0) printf("%lld
    ",n);
    30             else if(n%4==1) printf("1
    ");
    31             else if(n%4==2) printf("%lld
    ",n+1);
    32             else if(n%4==3) puts("0");
    33             continue;
    34         }
    35         if(k==2) {
    36             
    37         }
    38         ll m=1,res=0;
    39         int tt=0;
    40         for(tt=0;res<n;tt++)
    41         {
    42             sum[tt]=m;res+=m;
    43             if(m*k+res<=n) m=m*k;
    44             else m=n-res;
    45             if(!tt) t[tt]=1;
    46             else t[tt]=t[tt-1]*k+1;
    47         }
    48         ll ans=0;
    49         if(sum[tt-1]&1) ans=1;
    50         --tt;
    51         ll M;
    52         ll s1=k+1,s2=1,s3=0;
    53         if(sum[tt]%k!=0) {
    54             M=sum[tt]/k+1;
    55             s3=sum[tt]%k+1;
    56         }
    57         else {
    58             M=sum[tt]/k;
    59             s3=k+1;
    60         }
    61         int len=2;
    62         for(int i=tt-1;i>=0;i--)
    63         {
    64             if(M>=2&&((M-1)&1)) ans^=s1;
    65             ans^=s3;
    66             if((sum[i]-M)&1) ans^=s2;
    67             ll j;
    68             if(M%k==0) j=k;else j=M%k;
    69             s3=s1*(j-1)+s3+(k-j)*s2+1;
    70             if(M%k==0) M=M/k;
    71             else M=M/k+1;
    72             s1=t[len];
    73             s2=t[len-1];
    74             len++; 
    75         }
    76         printf("%lld
    ",ans);
    77     }
    78     return 0;
    79 }
    View Code

    Problem 1005

    答案就是(n+1)/2+1

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 const int inf=(1<<30)-1;
     4 const int maxn=100010;
     5 #define REP(i,n) for(int i=(0);i<(n);i++)
     6 #define FOR(i,j,n) for(int i=(j);i<=(n);i++)
     7 typedef long long ll;
     8 typedef pair<int,int> PII;
     9 int IN(){
    10     int c,f,x;
    11     while (!isdigit(c=getchar())&&c!='-');c=='-'?(f=1,x=0):(f=0,x=c-'0');
    12     while (isdigit(c=getchar())) x=(x<<1)+(x<<3)+c-'0';return !f?x:-x;
    13 }
    14 #define de(x) cout << #x << "=" << x << endl
    15 #define MP make_pair
    16 #define PB push_back
    17 #define fi first
    18 #define se second
    19 int a,b,T;
    20 int vis[maxn];
    21 int main()
    22 {
    23     scanf("%d",&T);
    24     while(T--)
    25     {
    26         scanf("%d",&a);
    27         printf("%d
    ",(a+1)/2+1);
    28     } 
    29     return 0;
    30 }
    View Code

    problem 1006

    考虑分组背包

    首先把数分组

    2, 4, 6, 8, 10, 12, 14, 16, ...

    3, 6, 9, 12, 15, 18, 21, 24...

    5, 10, 15, 20, 25, 30...

    7, 14, 21, 28, 35, 42...

    11, 22, 33, 44, 55, 66...

    13, 26, 39, 52, 65, 78...

    17, 34, 51, 68, 85, 102...

    19, 38, 57, 76, 95, 114...

    23, 46, 69, 92...

    29, 58, 87, 116..

    31, 62, 93, 124...

    ...

    ...

    这么分组之后我们发现,有某些数被分到了多组

    比如12,因为12既可以被2整除也可以被3整除

    仔细找规律我们发现从23开始的每个组的每个数都只属于一组。

    而前8组可能会有重复的数的出现。

    这样的话,我们把前面8组先预处理一下,

    设f[mask][i]为mask状态下选了i个数的方案数。

    然后再进行分组背包。

    #include <bits/stdc++.h>
    
    using namespace std;
    
    #define rep(i, a, b)	for (int i(a); i <= (b); ++i)
    #define dec(i, a, b)	for (int i(a); i >= (b); --i)
    
    typedef long long LL;
    
    const int N = 510;
    const LL mod = 1e9 + 7;
    
    LL f[305][N];
    int b1[N], b2[N], prime[N], state[N];
    int cnt = 0;
    int n, K;
    int T;
    LL  ans;
    
    void init(){
    	rep(i, 2, 503){
    		bool fl = true;
    		rep(j, 2, (int)sqrt(i + 0.5)) if (i % j == 0){
    			fl = false;
    			break;
    		}
    
    		if (fl) prime[cnt++] = i;
    
    	}
    
    	for (int i = 2; i * i <= 500; ++i)
    		for (int j = i * i; j <= 500; j += i * i) b1[j] = 1;
    
    	rep(i, 8, cnt - 1)
    		for (int j = 1; j * prime[i] <= 500; ++j) b2[j * prime[i]] = 1;
    
    	rep(i, 2, 500){
    		if (b1[i]) continue;
    		rep(j, 0, 7) if (i % prime[j] == 0) state[i] |= (1 << j);
    	}
    }
    
    int main(){
    
    	init();
    	scanf("%d", &T);
    	while (T--){
    		scanf("%d%d", &n, &K);
    		memset(f, 0, sizeof f);
    		f[0][0] = 1;
    		rep(i, 1, n){
    			if (b1[i] || b2[i]) continue;
    			dec(j, 255, 0) if (!(state[i] & j))
    				dec(k, K - 1, 0) (f[state[i] | j][k + 1] += f[j][k]) %= mod;
    		}
    
    		rep(i, 8, cnt - 1){
    			dec(k, K - 1, 0){
    				dec(j, 255, 0){
    					if (!f[j][k]) continue;
    					for (int times = 1, num; (num = times * prime[i]) <= n; ++times){
    						if (b1[num]) continue;
    						if (j & state[num]) continue;
    						(f[state[num] | j][k + 1] += f[j][k]) %= mod;
    					}
    				}
    			}
    		}
    
    		ans = 0;
    		rep(k, 1, K) rep(i, 0, 255) (ans += f[i][k]) %= mod;
    		printf("%lld
    ", ans);
    	}
    
    	return 0;
    }
    

    Problem 1008

    考虑直线近似经过每一个点

    每个点同时考虑2种情况

    即不到一点和超过一点

    极角排序后扫一圈

    二分判断下另一边过哪里

    维护前缀和后进行计算即可

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cmath>
      4 #include<cstdlib>
      5 #include<algorithm>
      6 #include<cstring>
      7 #include<string>
      8 #include<vector>
      9 #include<map>
     10 #include<set>
     11 #include<queue>
     12 using namespace std;
     13 typedef long long ll;
     14 struct point
     15 {
     16     ll x,y,val;
     17     point(){}
     18     point(ll _x,ll _y):x(_x),y(_y)
     19     {}
     20     point operator -(const point &b) const
     21     {
     22         return point(x-b.x,y-b.y);
     23     }
     24     ll operator *(const point &b) const
     25     {
     26         return x*b.x+y*b.y;
     27     }
     28     ll operator ^(const point &b) const
     29     {
     30         return x*b.y-y*b.x;
     31     }
     32 };
     33 ll _,n;
     34 point p[50010];
     35 ll sum[50010],pre[50010];
     36 ll cross(point sp,point ep,point op)
     37 {
     38     return (sp.x-op.x)*(ep.y-op.y)-(sp.y-op.y)*(ep.x-op.x);
     39 }
     40 inline bool cmp(const point &p1,const point &p2)
     41 {
     42     point o;
     43     o.x=o.y=0;
     44        return cross(p1,p2,o)>0;    
     45 }
     46 ll calc(ll pos,ll l,ll r)
     47 {
     48     if (l>r) return 0;
     49     l=l+pos;
     50     r=r+pos;
     51     if (l>n) l-=n;
     52     if (r>n) r-=n;
     53     if (l<=0) l+=n;
     54     if (r<=0) r+=n;
     55     if (l>r)
     56         return (pre[n]-pre[l-1]+pre[r]);
     57     else return pre[r]-pre[l-1];
     58 }
     59 int main()
     60 {
     61     scanf("%lld",&_);
     62     while (_--)
     63     {
     64         scanf("%lld",&n);
     65         ll i;
     66         for (i=1;i<=n;i++)
     67             scanf("%lld%lld%lld",&p[i].x,&p[i].y,&p[i].val);
     68         point o;
     69         o.x=0;
     70         o.y=0;
     71         sort(p+1,p+n+1,cmp);
     72         memset(pre,0,sizeof(pre));
     73         for (i=1;i<=n;i++)
     74             pre[i]=pre[i-1]+p[i].val;
     75         ll ans=0;
     76         //cout<<p[1].x<<" "<<p[1].y<<endl;
     77         //cout<<p[2].x<<" "<<p[2].y<<endl;
     78         for (i=1;i<=n;i++)
     79         {
     80             ll l=1,r=n-1;
     81             while (l<=r)
     82             {
     83                 ll mid=(l+r)>>1;
     84                 ll pos=i+mid;
     85                 pos%=n;
     86                 //cout<<i<<" "<<mid<<" "<<pos<<endl;
     87                 ll x=cross(p[i],p[pos],o);
     88                 if (x<0) r=mid-1;
     89                     else l=mid+1;            
     90             }
     91             ll up=calc(i,1,r);
     92             ll down=calc(i,r+1,n-1);
     93             ll sum=up*down;
     94             //cout<<i<<" "<<r<<" "<<up<<" "<<down<<endl;
     95             ans=max(ans,sum+p[i].val*up);
     96             ans=max(ans,sum+p[i].val*down);
     97         }
     98         printf("%lld
    ",ans);
     99     }
    100     return 0;
    101 }
    View Code

    Problem 1011

    直接在数列的后面加数即可

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cmath>
     4 #include<cstdlib>
     5 #include<algorithm>
     6 #include<cstring>
     7 #include<string>
     8 #include<vector>
     9 #include<map>
    10 #include<set>
    11 #include<queue>
    12 using namespace std;
    13 int p[10000010];
    14 void init()
    15 {
    16     p[1]=1;
    17     p[2]=2;
    18     int j=2,i=2,x=2;
    19     while (i<=10000000)
    20     {
    21         for (int k=1;k<=p[j];k++)
    22             p[i++]=x;
    23         j++;
    24         if (x==1) x=2; else x=1;
    25     }
    26 }
    27 int main()
    28 {
    29     init();
    30     int _;
    31     scanf("%d",&_);
    32     while (_--)
    33     {
    34         int x;
    35         scanf("%d",&x);
    36         printf("%d
    ",p[x]);
    37     }
    38     return 0;
    39 }
    View Code
  • 相关阅读:
    LeetCode 515. 在每个树行中找最大值(Find Largest Value in Each Tree Row)
    LeetCode 114. 二叉树展开为链表(Flatten Binary Tree to Linked List)
    LeetCode 199. 二叉树的右视图(Binary Tree Right Side View)
    LeetCode 1022. 从根到叶的二进制数之和(Sum of Root To Leaf Binary Numbers)
    LeetCode 897. 递增顺序查找树(Increasing Order Search Tree)
    LeetCode 617. 合并二叉树(Merge Two Binary Trees)
    LeetCode 206. 反转链表(Reverse Linked List) 16
    LeetCode 104. 二叉树的最大深度(Maximum Depth of Binary Tree)
    LeetCode 110. 平衡二叉树(Balanced Binary Tree) 15
    LeetCode 108. 将有序数组转换为二叉搜索树(Convert Sorted Array to Binary Search Tree) 14
  • 原文地址:https://www.cnblogs.com/cxhscst2/p/7441955.html
Copyright © 2011-2022 走看看