基础赛;

A,2,3,4,5,6,7,8,9 共9张纸牌排成一个正三角形(A按1计算)。要求每个边的和相等。
下面就是一种排法
   A
  9 6
 4   8
3 7 5 2
这样的排法可能会有很多。
如果考虑旋转、镜像后相同的算同一种,一共有多少种不同的排法呢?

提示:
1、正三角形有三个角,所以一个数字可以在三个角各出现一次,这就相当于旋转。
2、在生活中你照镜子的时候会发现,当你抬起左手时,你会看到镜子中的你会抬起右手。在本题中滤镜前后包括一个正三角形和该正三角形左右位置对称交换后的正三角形
 

 
#include <bits/stdc++.h>
#define ll long long
using namespace std;
int main()
{
      int a[9] = {1, 2, 3, 4, 5, 6, 7, 8, 9};//如果没有排好要sort
      int res = 0;
      do
      {
         int x1 = a[0] + a[1] + a[2] + a[3];
         int x2 = a[3] + a[4] + a[5] + a[6];
         int x3 = a[6] + a[7] + a[8] + a[0];
          if(x1==x2&&x2==x3) res++;
      } while (next_permutation(a, a + 9));//按字典序全排序 
      cout << res / 3 / 2 << endl;
      return 0;
}

 知识点:

next_permutation

按已有序列往下全排序 ; 

求当前排列的下一个排列(按字典序升序的下一个序列)如1234的next_permutation是1243

---

四平方和定理,又称为拉格朗日定理:

每个正整数都可以表示为至多4个正整数的平方和。

如果把0包括进去,就正好可以表示为4个数的平方和。

比如:

  1. 5 = 0^ 2 + 0^ 2 + 1^ 2 + 2^2

  2. 7 = 1^ 2 + 1^ 2 + 1^ 2 + 2^2

  3. (^符号表示乘方的意思)

对于一个给定的正整数,可能存在多种平方和的表示法。

要求你对4个数排序:

0 <= a <= b <= c <= d

并对所有的可能表示法按 a,b,c,d 为联合主键升序排列,最后输出第一个表示法

程序输入为一个正整数N (N<5000000)

要求输出4个非负整数,按从小到大排序,中间用空格分开

例如,输入:

5

则程序应该输出:

0 0 1 2
#include <bits/stdc++.h>
using namespace std;

typedef long long LL;
const int MAXN = 2500010;
struct Node
{
    int s, c, d;
    bool operator<(const Node &t) const//小于符号的定义
    {
        if (s != t.s)
            return s < t.s;
        if (c != t.c)
            return c < t.c;
        return d < t.d;
    }
} sum[MAXN];
/*
773535
1 1 267 838
*/
int n, m;
int main()
{
    cin >> n;
    for (int c = 0; c * c <= n; c++)
        for (int d = c; c * c + d * d <= n; d++)
            sum[m++] = {c * c + d * d, c, d}; //找所有的平方对子;
    sort(sum, sum + m);//排序 
    for (int a = 0; a * a <= n; a++)
    {
        for (int b = 0; a * a + b * b <= n; b++)
        {
            int t = n - a * a - b * b;
            int l = 0, r = m - 1;
            while (l < r)
            {
                       int mid=(r+l )>>2;    
                if (sum[mid].s >= t)
                    r = mid;
                else 
                    l = mid + 1;
            }

            if (sum[l].s == t)
            {
                printf("%d %d %d %d", a, b, sum[l].c, sum[l].d);
                return 0;
            }
        }
    }
    return 0;
}

k倍区间

给定一个长度为N的数列,A1, A2, … AN,如果其中一段连续的子序列Ai, Ai+1, … Aj(i <= j)之和是K的倍数,我们就称这个区间[i, j]是K倍区间。

你能求出数列中总共有多少个K倍区间吗?

输入格式

第一行包含两个整数N和K。(1 <= N, K <= 100000)

以下N行每行包含一个整数Ai。(1 <= Ai <= 100000)

输出格式

输出一个整数,代表K倍区间的数目。


#include <bits/stdc++.h>
using namespace std;
 
int main()
{
    long long n, k, ans = 0;
    int son[100000];// 储存数
    int sum[100000];// 储存前x项的余数和
    int b[100000] = {0}; // 储存相同余数的区间的个数
    cin >> n >> k;
    for (int i = 0; i < n; i++)
    {
        cin >> son[i];
//求余数
        if (i != 0)
           sum[i] = (sum[i - 1] + son[i]) % k;
//如果不是第一个数,输入的数与前面残留余数的和除余数等于新的前i项和的余数
        else
            sum[i] = son[i] % k;

        b[sum[i]]++;// 余数为k的区间个数+1
        ans += b[sum[i]] - 1;// 余数相同的相隔区间是K倍区间
        if (sum[i] == 0)//这里表示的就是前i项和恰为k的倍数的情况
            ans++;
    }
    cout << ans;
    return 0;
long pow_2(int b)//快速幂 以logn求2的幂次
{
    long x = 2;
    long res = 1;
    while (b > 0)
    {
        if (b & 1)
            res *= x;//2^5=2*2^4   101
        b >>= 1;
        x = x * x;
    }
    return res;
}
int gcd(long a, long b)//求最大公因数
{
    if (b == 0)
        return a;//递归出口
    return gcd(b, a % b);//递归调用
}

到x星球旅行的游客都被发给一个整数,作为游客编号。

x星的国王有个怪癖,他只喜欢数字3,5和7。

国王规定,游客的编号如果只含有因子:3,5,7,就可以获得一份奖品。

我们来看前10个幸运数字是:

3 5 7 9 15 21 25 27 35 45  

因而第11个幸运数字是:49

小明领到了一个幸运数字 59084709587505,他去领奖的时候,人家要求他准确地说出这是第几个幸运数字,否则领不到奖品。

请你帮小明计算一下,59084709587505是第几个幸运数字。

 

set


set<int> st;//声明了int类型的集合
set<int,cmp> stt;//按cmp规定的顺序排序
swap(st,st1);//交换两个集合中的元素
st.size();//返回集合的元素个数
st.empty();//如果集合为空,返回真

st.insert(i);
st.erase(i);

st.erease(i,j);// 删除[i,j)的区间元素
st.clear();
st.find(key);//返回key所在的位置
st.count(key);  //返回值为集合中键key的元素个数 在set中只能是0/1
st.upper_bound(key);  //返回第一个键大于key的元素的迭代器
st.lower_bound(key);  //返回第一个键大于等于key的元素的迭代器
  set<LL>::iterator it;//定义指向set的指针
 for (it = st.begin(); it != st.end(); it++)
    {
        if (*it <= maxs)
            num++;
    }

 

#include<cstring>
#include<algorithm>
#include <iostream>
#include <set>

using namespace std;

typedef long long LL;
const LL Max = 59084709587505;
int a[3] = {3, 5, 7};

void Find(LL Max)
{
    set<LL> se;
    //在集合中,所有的元素只能出现一次,并且默认按照元素的值从小到大自动排序
    LL t = 1;
    while (1)
    {
        for (int i = 0; i < 3; ++i)
        {
            LL tt = t * a[i];
            if (tt <= Max)
                se.insert(tt);//按顺序插入 3 5 7 9 15 21 25  35
        }
        t = *se.upper_bound(t);//返回第一个键大于key的元素的迭代器 1 3 5
        // 注意这里要用*;返回的迭代器是一个地址;
        if (t == Max)
            break;
    }
    cout << se.size() << endl;
}
int main(void)
{

    Find(Max);

    return 0;
}
//------
#include<iostream>
#include<queue>
#include<vector>
#include<set>

using namespace std;
int main()
{
    set<long long> st;
    priority_queue<long long ,vector<long long>, greater<long long> > pq;
    //优先输出小数据; 
//priority_queue<long long ,vector<long long>, less<long long> > pq; 
//与默认设置相同,优先输出大数据
    const int ok[3] = {3, 5, 7};
    st.insert(1);
    pq.push(1);//把1推入队列
    int times = 0;
    while (true)
    {
        long long lucky = pq.top();//把对头的值赋给lucky
        pq.pop();//推出对头

        if (lucky == 59084709587505)//判断出口
        {
            cout << times << endl;
            return 0;
        }
        times++;//记录lucky的数
        for (int i = 0; i < 3; i++)
        {
            long long b = lucky * ok[i];
            if (!st.count(b))
            {
                st.insert(b);//把b加入到st
                pq.push(b);//把b推入队列
            }
        }
    }
    return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值