牛客网练习赛 41

A:

中文题意,直接说思路

可以知道在n%m == 0 的时候可以全部翻转完,但当第一次翻转完之后B使坏一次就永远也翻不到,所以只有当n==m的时候是YES其他都是NO

代码:

#include 
using namespace std;
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        int a,b;
        scanf("%d%d",&a,&b);
        if(a != b) puts("No");
        else puts("Yes");
    }
}

B:

思路:

简单的计数dp,可以设 dp[i][j]表示的是你在第i轮凑到j数字的时候的方案数是多少,那么这个状态可以是从dp[i-1][j-a[i]] 和 dp[i-1][-j]分别加上a[i]和乘-1转移过来,所以加个和,由于666的性质,我们每次都让dp[][666]等于0就好了,因为a[i]有负数所以要加一个偏移量,这样开的数组大小将会达到 300 * 666*2,会炸内存,由dp[i]只能由dp[i-1]转移过来,所以我们可以用滚动数组优化一下

代码:

#include 
using namespace std;
const int tot = 300 * 666;
const int MOD = 1e8+7;
int dp[2][tot*2+1000] , a[333];
int main()
{
    int n;
    scanf("%d",&n);
    int sum = 0;
    for(int i = 1 ; i <= n ; i++) scanf("%d",&a[i]) , sum += abs(a[i]);
    int k = 0;
    dp[0][tot] = 1;
    for(int i = 1 ; i <= n ; i++)
    {
        k = k ^ 1;
        for(int j = -tot ; j < tot ; j ++)
        {
            if(j + tot - a[i] >= 0) dp[k][j+tot] = dp[k^1][j+tot-a[i]];
            if(tot - j >= 0) dp[k][j+tot] += dp[k^1][tot-j];
            //dp[k][j+tot] = (dp[k^1][j+tot-a[i]] + dp[k^1][tot-j]) % MOD;
            dp[k][j+tot] %= MOD;
        }
        dp[k][tot+666] = 0;
    }
    cout<

C:

思路:我们可以得出,最后这点都会被分成几个点集,然后每个点集都由一个总的权值,我们在点集中的某些点中设置一个路障就可以得到点集中所有的权值,所以我们的问题现在就变成了如何求这些点的点集,我们用并查集找到这些点集,并求这些点集的和,之后按照从大到小排序求前m个就好了,对了坑点是long long。

代码:

#include 
using namespace std;
#define int long long
const int maxn = 1e5+10;
int p[maxn] , ans[maxn] , a[maxn];
int getf(int x)
{
    return x == p[x] ? x : p[x] = getf(p[x]);
}
signed main()
{
    int n,m,t;
    scanf("%d%d",&n,&m);
    for(int i = 1 ; i <= n ; i++) p[i] = i;
    for(int i = 1 ; i <= n ; i++) scanf("%lld",&a[i]);
    for(int i = 1 ; i <= n ; i++)
    {
        scanf("%lld",&t);
        int dx = getf(t);
        int dy = getf(i);
        if(dx != dy)
        {
            p[dx] = dy;
        }
    }
    for(int i = 1 ; i <= n ; i++) ans[getf(i)] += a[i];
    sort(ans+1,ans+n+1,[](int a,int b){return a > b;});
    int ANS = 0;
    for(int i = 1 ; i <= m ; i++) ANS += ans[i];
    cout<

D:

思路:可以发现,m只有20,那么总共的方案数其实也就(1<<20)个,我们把这n个数放到bfs里面跑一下,求出这n个数能够变成的所有数所需要的最小步数,之后用m减去最小步数就好了。 这里解释一下

 int v = (u^(1< dis[u] + 1)
 {
    dis[v] = dis[u] + 1;
    Q.push(v);
 }

首先我们有u这个二进制数,我们现在由u这个数开始扩展,找到一个改变u的某一位之后两个异或会产生1的数字,那么假设u的第j位是0,那么我们就要找到一个数v除了第j位位1其他都是0的数,假设u的第j位是1相反,那么这个v就是 u^(1<

代码:

#include 
using namespace std;
const int INF = 0x3f3f3f3f;
const int maxn = 3e5+100;
char ch[maxn][22];
int dis[1<<20];
queueQ;
int main()
{
    int n , m;
    scanf("%d%d",&n,&m);
    for(int i = 0 ; i < (1<>ch[i];
        int x = 0;
        for(int j = 0 ; j < m ; j++)
        {
            if(ch[i][j] == '1') x |= (1< dis[u] + 1)
            {
                dis[v] = dis[u] + 1;
                Q.push(v);
            }
        }
    }
    int ans = INF;
    for(int i = 0 ; i < (1<

F:

思路:拉一个求球冠的板子就ok了

代码:

#include
using namespace std;
const int maxn = 105;
const double PI = acos(-1);
typedef struct point {
    double x,y,z;
    point() {
  
    }
    point(double a, double b,double c) {
        x = a;
        y = b;
        z = c;
    }
    point operator -(const point &b)const {     //·µ»Ø¼õÈ¥ºóµÄеã
        return point(x - b.x, y - b.y,z-b.z);
    }
    point operator +(const point &b)const {     //·µ»Ø¼ÓÉϺóµÄеã
        return point(x + b.x, y + b.y,z+b.z);
    }
    //Êý³Ë¼ÆËã
    point operator *(const double &k)const {    //·µ»ØÏà³ËºóµÄеã
        return point(x * k, y * k,z*k);
    }
    point operator /(const double &k)const {    //·µ»ØÏà³ýºóµÄеã
        return point(x / k, y / k,z/k);
    }
    double operator *(const point &b)const {    //µã³Ë
        return x*b.x + y*b.y+z*b.z;
    }
}point;
double dist(point p1, point p2) {       //·µ»ØƽÃæÉÏÁ½µã¾àÀë
    return sqrt((p1 - p2)*(p1 - p2));
}
typedef struct sphere {//Çò
    double r;
    point centre;
}sphere;
double SphereInterVS(sphere a, sphere b) {
    double d = dist(a.centre, b.centre);//ÇòÐľà
    double t = (d*d + a.r*a.r - b.r*b.r) / (2.0 * d);//
    double h = sqrt((a.r*a.r) - (t*t)) * 2;//h1=h2£¬Çò¹ÚµÄ¸ß
    double angle_a = 2 * acos((a.r*a.r + d*d - b.r*b.r) / (2.0 * a.r*d));  //ÓàÏÒ¹«Ê½¼ÆËãr1¶ÔÓ¦Ô²ÐĽǣ¬»¡¶È
    double angle_b = 2 * acos((b.r*b.r + d*d - a.r*a.r) / (2.0 * b.r*d));  //ÓàÏÒ¹«Ê½¼ÆËãr2¶ÔÓ¦Ô²ÐĽǣ¬»¡¶È
    double l1 = ((a.r*a.r - b.r*b.r) / d + d) / 2;
    double l2 = d - l1;
    double x1 = a.r - l1, x2 = b.r - l2;//·Ö±ðΪÁ½¸öÇòȱµÄ¸ß¶È
    double v1 = PI*x1*x1*(a.r - x1 / 3);//Ïཻ²¿·Ör1Ô²Ëù¶ÔÓ¦µÄÇòȱ²¿·ÖÌå»ý
    double v2 = PI*x2*x2*(b.r - x2 / 3);//Ïཻ²¿·Ör2Ô²Ëù¶ÔÓ¦µÄÇòȱ²¿·ÖÌå»ý
    double  v = v1 + v2;//Ïཻ²¿·ÖÌå»ý
    return v;
}
  
sphere qiu[maxn],s;
  
int main()
{
  
    int z, CASE = 1;
    scanf("%lf%lf%lf%lf",&qiu[0].centre.x,&qiu[0].centre.y,&qiu[0].centre.z,&qiu[0].r);
    scanf("%lf%lf%lf%lf",&s.centre.x,&s.centre.y,&s.centre.z,&s.r);
    double ans = 0.0;
    double V ,S ;
    double dis = dist(qiu[0].centre,s.centre);
    double p = max(qiu[0].r,s.r);
    double q = min(qiu[0].r,s.r);
    if(dis >= qiu[0].r + s.r)
    {
        ans += (4.0/3.0)*PI*qiu[0].r*qiu[0].r*qiu[0].r;
        ans += (4.0/3.0)*PI*s.r*s.r*s.r ;
        printf("%.7f\n",ans);
    }
    else if(dis + q <= p || dis + p <= q)
    {
          
        ans += (4.0/3.0)*PI*p*p*p;
        printf("%.7f\n",ans);
        return 0;
    }
    else
    {
        ans =  (4.0/3.0)*PI*qiu[0].r*qiu[0].r*qiu[0].r + (4.0/3.0)*PI*s.r*s.r*s.r - SphereInterVS(qiu[0],s);
        printf("%.7f\n",ans);
    }
}

 

你可能感兴趣的:(牛客网练习赛 41)