National Contest for Private Universities (NCPU), 2019 (无向图统计简单环个数)

National Contest for Private Universities (NCPU), 2019

 常见问题

  • 题目列表
  • 我的提交
  • 排名:21
  • 问答
  •  A. Minimum Factorial as a Multiple

    • 通过率:80.68%
    • 正确提交 / 总提交:284 / 352
  •  B. Population Count

    • 通过率:93.73%
    • 正确提交 / 总提交:269 / 287
  •  C. Boxes

    • 通过率:22.4%
    • 正确提交 / 总提交:71 / 317
  •  D. RSSI fingerprinting

    • 通过率:56.38%
    • 正确提交 / 总提交:212 / 376
  •  E. Generalized Pascal's Triangle

    • 通过率:48.5%
    • 正确提交 / 总提交:146 / 301
  •  F. Sequence Decoding

    • 通过率:77.98%
    • 正确提交 / 总提交:170 / 218
  •  G. Cycles

    • 通过率:19.8%
    • 正确提交 / 总提交:40 / 202
  •  H. Countable Rational Numbers

    • 通过率:48.28%
    • 正确提交 / 总提交:14 / 29

 

A-Minimum Factorial as a Multiple 
题意:求满足 k! mod n = 0 的最小 k

枚举 k 即可 

#include 

using namespace std;

int fac[20];
int main(){
	int m,n;
	scanf("%d",&m);
	fac[1]=1;
	for(int i=2;i<=12;i++)fac[i]=i*fac[i-1];
	while(m--){
		
		scanf("%d",&n);
		for(int i=1;i<=12;i++){
			if(fac[i]%n==0){
				printf("%d\n",i);
				break;
			}
		}
	}
	return 0;
}

 

 

B-Population Count 
题意:求 b 到 e 区间内的每个数在二进制下 1 的个数之和

由于 b 和 e 的范围较小,枚举 b 到 e 区间的每一个数,转化为二进制按位统计即可。 

#include
using namespace std;
#define MAXN 500005
typedef long long LL;
const LL MOD=1e9+7;
int n;
int solve(int n)
{
	int i=0;
	while(n)
	{
		if(n%2==1)
			i++;
		n/=2;
		
	}
	return i;
}
int main()
{
    int n;
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
	{
		int b,e;
		scanf("%d%d",&b,&e);
		LL ans=0;
		for(int i=b;i<=e;i++)
		{
			ans+=solve(i);
			///cout<


C-Boxes 
题意:对 1-n 的数列进行元素移动、互换、倒转等操作,求最后序列的奇数位之和.

题目解析 利用双向链表记录数列,模拟对应操作。对于数列倒转操作,只需记录倒转次数,奇数次倒 转时将操作 1、2 互换即可。需注意 x,y 相邻时特殊处理。 

#include
using namespace std;
typedef long long LL;
const int N=100005;
struct Node
{
    int l,r;
} a[N];
void link(int x,int y)
{

    a[x].r=y;
    a[y].l=x;
}

int main()
{
    int n,m;

    while(scanf("%d%d",&n,&m)!=-1)
    {

        a[0].r=1;
        a[0].l=n;
        for(int i=1; i<=n; i++)
        {
            a[i].l=i-1;
            a[i].r=(i+1)%(n+1);
        }

        int cnt=0;

        for(int i=1; i<=m; i++)
        {
            int op,x,y;
            scanf("%d",&op);
            if(op==4)
            {
                cnt++;
            }
            else
            {
                if(cnt&1)
                {
                    if(op==1)
                        op=2;
                    else if(op==2)
                        op=1;
                }

                if(op==1)
                {
                    scanf("%d%d",&x,&y);
                    if(a[y].l==x)
                        continue;
                    int lx=a[x].l,rx=a[x].r,ly=a[y].l,ry=a[y].r;
                    link(lx,rx);
                    link(ly,x);
                    link(x,y);
                }
                else if(op==2)
                {
                    scanf("%d%d",&x,&y);
                    if(a[y].r==x)
                        continue;
                    int lx=a[x].l,rx=a[x].r,ly=a[y].l,ry=a[y].r;
                    link(lx,rx);
                    link(y,x);
                    link(x,ry);

                }
                else if(op==3)
                {
                    scanf("%d%d",&x,&y);
                     if(a[y].r==x)
                        swap(x,y);

                    int lx=a[x].l,rx=a[x].r,ly=a[y].l,ry=a[y].r;


                    if(rx==y)
                    {
                        link(lx,y);
                        link(x,ry);
                        link(y,x);
                    }
                    else
                    {
                        link(lx,y);
                        link(y,rx);
                        link(ly,x);
                        link(x,ry);
                    }
                }
            }

        }
        int num = 0;
        LL ans = 0;
        for(int i = 1; i <= n; i++)
        {
            num = a[num].r;
            //cout<

D-RSSI fingerprinting 
题意:求 RSSI 中时间小于 1000,信号强度最大的 3 个(信号强度相等则字典序小优先)

将检测时间大于 1000 的删除,其余的按信号强度,字典序排序后输出前三项(不足三项 则全部输出)。

#include     //STL通用算法
#include      //STL位集容器
#include 
#include 
#include 
#include       //STL双端队列容器
#include     //异常处理类
#include 
#include    //STL定义运算函数(代替运算符)
#include 
#include       //STL线性列表容器
#include        //STL 映射容器
#include 
#include       //基本输入/输出支持
#include     //输入/输出系统使用的前置声明
#include 
#include      //基本输入流
#include      //基本输出流
#include       //STL队列容器
#include        //STL 集合容器
#include     //基于字符串的流
#include       //STL堆栈容器    
#include      //字符串类
#include      //STL动态数组容器
#define ll unsigned long long
using namespace std;
#define rep(i,a,b) for(register ll i=(a);i<=(b);i++)
#define dep(i,a,b) for(register ll i=(a);i>=(b);i--)
//priority_queue,less >q;
const ll maxn = 228+66;
const ll maxm=900000+66;
const ll mod=1e9+7;
const ll inf=0x3f3f3f3f3f3f3f3fLL;
const ll INF=99999999;
ll tot=0;
ll n;
bool vis[maxn];
ll f[]= {0,1,2,31,62,1847,3694,57257,114514};
struct node
{
    char ch[maxn*100];
    int r;
    ll t;
} a[maxn];
bool cmp(node a,node b)
{
   if(a.r!=b.r) return a.r>b.r;
   else return a.ch

 
E-Generalized Pascal's Triangle 
题意:给出一个立体的杨辉三角,每一层的每个数字等于该数字肩上的三个数字之和。

每一个点都可以对下一层的三个点产生贡献,第 i 层第 j 行第 k 列点产生贡献的三个点是第 i+1 行的第 j 列的第 k、k+1 个点及第 j+1 列的第 k+1 个点,递推即可。 

本题也可以发现是这样的。

n=3时;(x+y+z)^3

               1                                                          

         3          3

    3          6         3

1     3             3      1

 

                   1x^3                                                        

         3x^2y          3x^2z

    3xy^2          6xyz        3xyz^2

1y^3     3y^2z        3yz^2      1z^2

知道了(x+y+z)^n=f(n!/(r!*s!*t!)x^r*y^s*z^t),f()表示rst的全排列且r+s+t=n

然后模拟就行了,n!超longlong,大树走起

from queue import PriorityQueue
import sys

sys.setrecursionlimit(10**9)

IA = lambda: [int(x) for x in input().split()]
IM = lambda N: [IA() for _ in range(N)]
#!/usr/bin/env python3
# -*- coding: utf-8 -*-

ans=0
MOD = 1000000007
f=[int(1) for i in range(0,25)]
for i in range(1,22):
    for j in range(1,i+1):
        f[i]*=j;
    # print(f[i])
while True:
    try:
        n = int(input())
        num=int(0)
        for i in range(0, n + 1):
            t1 = n - i
            num = int(0)
            for j in range(0, n - t1 + 1):
                t2 = n - t1 - j
                for k in range(0, n - t2 - t1 + 1):
                    t3 = n - t2 - t1 - k

                    if (t1 + t2 + t3 != n): continue
                    num += 1

                    # print(str(t1)+str(t2)+str(t3),end='%');
                    if i==num-1:
                        print(int(f[n] / (f[t1] * f[t2] * f[t3])))
                    else:
                        print(int(f[n] / (f[t1] * f[t2] * f[t3])),end=' ')


    #except EOFError:break
    except:break



 


F-Sequence Decoding 
题意:一个字符串,包含数字、"[" 、"]"、字母 P 和 H ,每一个互相匹配的括号内的字符串 都重复"["前的数字 k 次,把字符串展开为只含字母的字符串。

模拟即可,每一个字符入栈,遇到"]"则将栈中"["后的字母全部取出,按照"["前的数字 k 入栈 k 次即可,最后栈中字符串即为答案。 

#include
using namespace std;
#define MAXN 500005
typedef long long LL;
const LL MOD=1e9+7;
int num[MAXN];
string str[MAXN];
void out(int cnt)
{
    cout<>s;
        s="1["+s+']';
        int len=s.size();
        for(int j=0; j='0')
            {
                num[cnt]=s[i]-'0';
                i++;
            }
            else if(s[i]=='[')
            {
                cnt++;
                i++;

            }
            else if(s[i]==']')
            {
                for(int j=0; j

G-Cycles 
题意:判断给定无向图是否联通并求出图中环的个数

同 Codeforces 11D。本题数据范围较小,使用并查集判断图是否联通,dfs 计算图中环的个数直至三个。最后按照题目要求输出答案即可。 

#include
using namespace std;
typedef long long ll;
const int maxn = 20;
int maze[maxn][maxn];
// dp[s][i] : 表示s状态下以 s 状态的最小顶点和顶点i构成的简单环 (这样仍然会重复计算2次)
ll dp[1<=2))
            printf("n\n");
        else if(ans/2>=3)
            printf("y: there are at least three cycles\n");
        else
            printf("y\n");
        
        
        
    }
    return 0;
}

National Contest for Private Universities (NCPU), 2019 (无向图统计简单环个数)_第1张图片

 

 

 

 

你可能感兴趣的:(模板,比赛题解)