National Contest for Private Universities (NCPU), 2019 (無向圖統計簡單環個數)

National Contest for Private Universities (NCPU), 2019

 常見問題

  •  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 <stdio.h>

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<bits/stdc++.h>
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<<ans<<endl;
		}
		cout<<ans<<endl;
	}
    return 0;
}


C-Boxes 
題意:對 1-n 的數列進行元素移動、互換、倒轉等操作,求最後序列的奇數位之和.

題目解析 利用雙向鏈表記錄數列,模擬對應操作。對於數列倒轉操作,只需記錄倒轉次數,奇數次倒 轉時將操作 1、2 互換即可。需注意 x,y 相鄰時特殊處理。 

#include<bits/stdc++.h>
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<<num<<" ";
            if(n%2==0&&cnt%2==1)
            {
                if(i%2==0)
                    ans+=num;
            }
            else
            {
                if(i%2==1)
                    ans+=num;
            }

        }
        cout<<ans<<endl;


    }

    return 0;
}

D-RSSI fingerprinting 
題意:求 RSSI 中時間小於 1000,信號強度最大的 3 個(信號強度相等則字典序小優先)

將檢測時間大於 1000 的刪除,其餘的按信號強度,字典序排序後輸出前三項(不足三項 則全部輸出)。

#include <algorithm>    //STL通用算法
#include <bitset>     //STL位集容器
#include <cmath>
#include <cstdio>
#include <cstring>
#include <deque>      //STL雙端隊列容器
#include <exception>    //異常處理類
#include <fstream>
#include <functional>   //STL定義運算函數(代替運算符)
#include <limits>
#include <list>      //STL線性列表容器
#include <map>       //STL 映射容器
#include <iomanip>
#include <ios>      //基本輸入/輸出支持
#include<iosfwd>     //輸入/輸出系統使用的前置聲明
#include <iostream>
#include <istream>     //基本輸入流
#include <ostream>     //基本輸出流
#include <queue>      //STL隊列容器
#include <set>       //STL 集合容器
#include <sstream>    //基於字符串的流
#include <stack>      //STL堆棧容器    
#include <string>     //字符串類
#include <vector>     //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<ll,vector<ll>,less<ll> >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<b.ch;
}
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        int n;
        scanf("%d",&n);
        rep(i,1,n)
        {
            scanf("%s %d %lld",a[i].ch,&a[i].r,&a[i].t);
        }
        sort(a+1,a+n+1,cmp);
        int yy=0;
        rep(i,1,n)
        {
            if(a[i].t<1000&&yy<3)
            {
                yy++;
                printf("%s %d\n",a[i].ch,a[i].r);
            }
        }
    }
    return 0;
}

 
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<bits/stdc++.h>
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<<cnt<<endl;
    for(int i=0; i<=cnt; i++)
    {
        cout<<num[i]<<"&"<<str[i]<<endl;
    }
    cout<<endl;
}
int main()
{
    int n;
    scanf("%d",&n);
    for(int t=1; t<=n; t++)
    {
        memset(num,0,sizeof(num)) ;

        int cnt=0;
        string s;
        cin>>s;
        s="1["+s+']';
        int len=s.size();
        for(int j=0; j<len; j++)
        {
            str[j]="";
        }
        for(int i=0; i<len;)
        {
            if(s[i]<='9'&&s[i]>='0')
            {
                num[cnt]=s[i]-'0';
                i++;
            }
            else if(s[i]=='[')
            {
                cnt++;
                i++;

            }
            else if(s[i]==']')
            {
                for(int j=0; j<num[cnt-1]; j++)
                    str[cnt-1]+=str[cnt];
				str[cnt]="";
                cnt--;
                i++;

            }
            else
            {
                string temp="";
                int j=i;
                while(s[j]=='H'||s[j]=='P')
                {
                    temp+=s[j];
                    j++;
                }
                str[cnt]+=temp;
                i=j;
            }
            //out(cnt);


        }
        cout<<str[0]<<endl;
    }
    return 0;
}

G-Cycles 
題意:判斷給定無向圖是否聯通並求出圖中環的個數

同 Codeforces 11D。本題數據範圍較小,使用並查集判斷圖是否聯通,dfs 計算圖中環的個數直至三個。最後按照題目要求輸出答案即可。 

#include<bits/stdc++.h>
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<<maxn][maxn];
int n,m;
int vis[maxn];
int cnt;
void dfs(int x)
{
	if(cnt==n) return ;
	for(int i=0;i<n;i++)
	{
		if(x==i) continue;
		if(maze[x][i]==1&&vis[i]==0)
		{
			//cout<<i<<"^^"<<endl;
			vis[i]=1;
			cnt++;
			if(cnt==n)
				return ;
			
			dfs(i);
		}
		if(cnt==n) return ;
	}
}
int main()
{
	int T;
	scanf("%d",&T);
    while(T--)
    {
    	scanf("%d%d",&n,&m);
        memset(dp,0,sizeof(dp));
           memset(vis,0,sizeof(vis));
        memset(maze,0,sizeof(maze));
        for(int i=0,u,v;i<m;i++) {
            scanf("%d%d",&u,&v);
            u--,v--;
            maze[u][v] = maze[v][u] = 1;
        }
        ll ans = 0;
        for(int i=0;i<n;i++) dp[1<<i][i] = 1;
        for(int s=1;s<(1<<n);s++) {
            int pre = log2(s & -s);
            for(int i=pre;i<n;i++) if(dp[s][i]){ /// 枚舉結尾的頂點
                for(int j = pre;j<n;j++) if(maze[i][j]){ /// 枚舉接下來要連接的頂點
                    if(s & (1<<j)) { /// 節點j在當前狀態中
                        if (((1<<i)|(1<<j))==s) continue; /// 排除兩個節點成環的情況
                        if(j == pre) ans += dp[s][i];
                    }                    
                    else { /// 節點j不在當前狀態中
                        dp[s|(1<<j)][j] += dp[s][i];
                    }
                }
            }
        }
        
        //printf("%lld\n",ans/2);
        cnt=1;
        vis[0]=1;
        dfs(0);
        //cout<<cnt<<endl;
		if(!(cnt==n&&ans/2>=2))
            printf("n\n");
        else if(ans/2>=3)
            printf("y: there are at least three cycles\n");
        else
            printf("y\n");
        
        
        
    }
    return 0;
}

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章