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;
}