SWPU暑假第一场训练赛题解

A.签到题吧(出题人好像原意并不是想这样,逃

B.大概就是二分再二分。

先排序,最大的肯定是a[m-1]*b[n-1],二分就是在l=0,r=a[m-1]*b[n-1] 里找

按照顺序来找。

a 0 1 2 3 4 5 `````

b 0 1 2 3 4 5 `````

如果是没有重复数字的情况下。

那么第K大的数一定是 m*x+y

比如K是 11 a有6个数

那么 b的第一个数乘以a的6个数 已经到了第6位。

b的第二个数乘a的5个数就到了11位。

所以二分找第k大的数

#include <cstdio>  
#include <iostream>  
#include <algorithm>  
using namespace std;  
const int maxn = 10005;  
#define ll long long  
int a[maxn];  
int b[maxn];  
int m, n, k;  
int getsum(int x)  
{  
    int l = 0, r = n - 1;  
    while (l <= r)  
    {  
        int mid = (l + r) >> 1;  
        if (b[mid] <= x)  
            l = mid + 1;  
        else  
            r = mid - 1;  
    }  
    return l;  
}  
bool check(int x)  
{  
    ll ans = 0;  
    for (int i = 0; i < m; i++)  
    {  
            if (!a[i])// 如果a[i] 是0的话 那么这一排m必取  
            {  
                ans += n;  
                continue;  
            }  
            int cnt = x / a[i];//a[i]* cnt=x; 求最大的cnt 其他比  
            //cnt小的 都要加起来  
            ans += getsum(cnt);//在b里找 比cnt小的  
    }  
     return ans >= k;  
}  
int main()  
{  
    scanf("%d %d %d",&m,&n,&k);  
    for(int i=0;i<m;i++) scanf("%d",&a[i]);  
    for(int i=0;i<n;i++) scanf("%d",&b[i]);  
    sort(a,a+m);  
    sort(b,b+n);  
    int l = 0;  
    int r = a[m-1]*b[n-1];  
    while(l<=r)  
    {  
        int mid = (l+r)>>1;  
        if(check(mid)) r = mid-1;  
        else l = mid+1;  
    }  
    cout << l << endl;  
}  
C.当然出题人想让大家使用O(n)过去,但事实出题人想了想,还是单case让O(nlogn)也过去。

或许你可以学学这个

然后自然就有了如下代码:

//china no.1
#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <vector>
#include <iostream>
#include <string>
#include <map>
#include <stack>
#include <cstring>
#include <queue>
#include <list>
#include <stdio.h>
#include <set>
#include <algorithm>
#include <cstdlib>
#include <cmath>
#include <iomanip>
#include <cctype>
#include <sstream>
#include <functional>
#include <stdlib.h>
#include <time.h>
#include <bitset>
using namespace std;
 
#define pi acos(-1)
#define PI acos(-1)
#define endl '\n'
#define srand() srand(time(0));
#define me(x,y) memset(x,y,sizeof(x));
#define foreach(it,a) for(__typeof((a).begin()) it=(a).begin();it!=(a).end();it++)
#define close() ios::sync_with_stdio(0); cin.tie(0);
#define FOR(x,n,i) for(int i=x;i<=n;i++)
#define FOr(x,n,i) for(int i=x;i<n;i++)
#define W while
#define sgn(x) ((x) < 0 ? -1 : (x) > 0)
#define bug printf("***********\n");
#define db double
typedef long long LL;
const int INF=0x3f3f3f3f;
const LL LINF=0x3f3f3f3f3f3f3f3fLL;
const int dx[]={-1,0,1,0,1,-1,-1,1};
const int dy[]={0,1,0,-1,-1,1,-1,1};
const int maxn=1e5+10;
const int maxx=1e6+100;
const double EPS=1e-8;
const double eps=1e-8;
const int mod=1e9+7;
template<class T>inline T min(T a,T b,T c) { return min(min(a,b),c);}
template<class T>inline T max(T a,T b,T c) { return max(max(a,b),c);}
template<class T>inline T min(T a,T b,T c,T d) { return min(min(a,b),min(c,d));}
template<class T>inline T max(T a,T b,T c,T d) { return max(max(a,b),max(c,d));}
template <class T>
inline bool scan_d(T &ret){char c;int sgn;if (c = getchar(), c == EOF){return 0;}
while (c != '-' && (c < '0' || c > '9')){c = getchar();}sgn = (c == '-') ? -1 : 1;ret = (c == '-') ? 0 : (c - '0');
while (c = getchar(), c >= '0' && c <= '9'){ret = ret * 10 + (c - '0');}ret *= sgn;return 1;}
 
inline bool scan_lf(double &num){char in;double Dec=0.1;bool IsN=false,IsD=false;in=getchar();if(in==EOF) return false;
while(in!='-'&&in!='.'&&(in<'0'||in>'9'))in=getchar();if(in=='-'){IsN=true;num=0;}else if(in=='.'){IsD=true;num=0;}
else num=in-'0';if(!IsD){while(in=getchar(),in>='0'&&in<='9'){num*=10;num+=in-'0';}}
if(in!='.'){if(IsN) num=-num;return true;}else{while(in=getchar(),in>='0'&&in<='9'){num+=Dec*(in-'0');Dec*=0.1;}}
if(IsN) num=-num;return true;}
 
void Out(LL a){if(a < 0) { putchar('-'); a = -a; }if(a >= 10) Out(a / 10);putchar(a % 10 + '0');}
void print(LL a){ Out(a),puts("");}
//freopen( "in.txt" , "r" , stdin );
//freopen( "data.txt" , "w" , stdout );
//cerr << "run time is " << clock() << endl;
 
//http://blog.csdn.net/oiljt12138/article/details/51174560
//因为这里要维护优先级的最小值,那么队列是单调减的,也说队列是单调减的。
struct node
{
    long long s;
    int n;
}q[1000010];
int a,n,m;
long long s[1000010],ans;
int h,t;
int main()
{
    //freopen( "1.txt" , "r" , stdin );
    //freopen( "3.out" , "w" , stdout );
    int T;
    //scanf("%d",&T);
    T=1;
    W(T--)
    {
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&a);
            s[i]=a+s[i-1];
        }
        q[0].s=0;q[0].n=0;
        for(int i=1;i<=n;i++)
        {
            long long r=s[i];
            r-=q[t].s;
            ans=max(ans,r);
            while(t<=h&&q[h].s>s[i])h--;
            q[++h].s=s[i];
            q[h].n=i;
            while(q[t].n<=i-m)t++;
        }
        cout<<ans<<endl;
    }
    return 0;
}
D.

先判断奇数个数,答案就是总数-偶数个数。

另:

其实组合数判断奇偶性有一个优美的结论

          

如果,那么为奇数,否则为偶数

 

当然本题要判断的组合数很多,所以不能用上述结论,只能另辟蹊径。由于是判断奇偶性,那么就是判断

是否为1,利用Lucas定理,先把化为二进制,这样它们都是01序列了。我们又知道

。这样中为0的地方对应的中的位置只有一种可能,那就是0

 

这样我们可以不用管中为0的地方,只考虑中为1的位置,可以看出,中为1的位置对应的中为0

1,其结果都是1,这样答案就是:n+1-1<<(二进制表示中1的个数)



然后这个题其实可以打表


//china no.1
#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <vector>
#include <iostream>
#include <string>
#include <map>
#include <stack>
#include <cstring>
#include <queue>
#include <list>
#include <stdio.h>
#include <set>
#include <algorithm>
#include <cstdlib>
#include <cmath>
#include <iomanip>
#include <cctype>
#include <sstream>
#include <functional>
#include <stdlib.h>
#include <time.h>
#include <bitset>
using namespace std;
 
#define pi acos(-1)
#define PI acos(-1)
#define endl '\n'
#define srand() srand(time(0));
#define me(x,y) memset(x,y,sizeof(x));
#define foreach(it,a) for(__typeof((a).begin()) it=(a).begin();it!=(a).end();it++)
#define close() ios::sync_with_stdio(0); cin.tie(0);
#define FOR(x,n,i) for(int i=x;i<=n;i++)
#define FOr(x,n,i) for(int i=x;i<n;i++)
#define W while
#define sgn(x) ((x) < 0 ? -1 : (x) > 0)
#define bug printf("***********\n");
#define db double
typedef long long LL;
const int INF=0x3f3f3f3f;
const LL LINF=0x3f3f3f3f3f3f3f3fLL;
const int dx[]={-1,0,1,0,1,-1,-1,1};
const int dy[]={0,1,0,-1,-1,1,-1,1};
const int maxn=1e5+10;
const int maxx=1e6+100;
const double EPS=1e-8;
const double eps=1e-8;
const int mod=1e9+7;
template<class T>inline T min(T a,T b,T c) { return min(min(a,b),c);}
template<class T>inline T max(T a,T b,T c) { return max(max(a,b),c);}
template<class T>inline T min(T a,T b,T c,T d) { return min(min(a,b),min(c,d));}
template<class T>inline T max(T a,T b,T c,T d) { return max(max(a,b),max(c,d));}
template <class T>
inline bool scan_d(T &ret){char c;int sgn;if (c = getchar(), c == EOF){return 0;}
while (c != '-' && (c < '0' || c > '9')){c = getchar();}sgn = (c == '-') ? -1 : 1;ret = (c == '-') ? 0 : (c - '0');
while (c = getchar(), c >= '0' && c <= '9'){ret = ret * 10 + (c - '0');}ret *= sgn;return 1;}
 
inline bool scan_lf(double &num){char in;double Dec=0.1;bool IsN=false,IsD=false;in=getchar();if(in==EOF) return false;
while(in!='-'&&in!='.'&&(in<'0'||in>'9'))in=getchar();if(in=='-'){IsN=true;num=0;}else if(in=='.'){IsD=true;num=0;}
else num=in-'0';if(!IsD){while(in=getchar(),in>='0'&&in<='9'){num*=10;num+=in-'0';}}
if(in!='.'){if(IsN) num=-num;return true;}else{while(in=getchar(),in>='0'&&in<='9'){num+=Dec*(in-'0');Dec*=0.1;}}
if(IsN) num=-num;return true;}
 
void Out(LL a){if(a < 0) { putchar('-'); a = -a; }if(a >= 10) Out(a / 10);putchar(a % 10 + '0');}
void print(LL a){ Out(a),puts("");}
//freopen( "in.txt" , "r" , stdin );
 
//cerr << "run time is " << clock() << endl;
 
 
int n;
int main()
{
    int t;
    //freopen( "5.txt" , "w" , stdout );
    scan_d(t);
    W(t--)
    {
        scan_d(n);
        int t=1,cnt=0,k=n+1;
        W(n)
        {
            if(n&t)
                cnt++;
            n>>=1;
        }
        print(k-(1<<cnt));
    }
}

E.







  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值