9.6 模拟试题
?XXY 的?NOIP 模擬賽?1
| 題目 | ? | 全排列 | ? | ? | 走樓梯 | 部落 |
| ? | ? | ? | ? | ? | ? | |
| ? | ? | ? | ? | ? | ? | ? |
| ? | ? | ? | ? | ? | stair | people |
| 英文題目與子目錄名 | ? | permutation | ? | |||
| ? | ? | |||||
| ? | ? | ? | ? | ? | ? | ? |
| 單個測試點時間限制 | ? | 1秒 | ? | ? | 1秒 | 1秒 |
| ? | ? | ? | ? | ? | ? | ? |
| 內存限制 | ? | 128M | ? | ? | 128M | 128M |
| ? | ? | ? | ? | ? | ? | |
| 測試點數目 | ? | 10 | ? | 10 | 10 | |
| ? | ? | ? | ? | ? | ? | |
| 每個測試點分值 | ? | 10 | ? | 10 | 10 | |
| ? | ? | ? | ? | ? | ||
| 比較方式 | ? | 全文比較(過濾行末空格及文末回車) | ||||
| ? | ? | ? | ? | ? | ? | ? |
| 題目類型 | ? | 傳統 | ? | ? | 傳統 | 傳統 |
| ? | ? | ? | ? | |||
| ? | ? | ? | ? | ? | ? | ? |
?
?
全排列
Description
從 n?個不同元素中任取 m(m≤n)個元素,按照一定的順序排列起來,叫做從 n?個不同元素中取出 m 個元素的一個排列。當?m=n 時所有的排列情況叫全排列。把全排列按字典序排序,現在?xxy 想問你第 x?個全排列是什么,或給定的排列 p?是第幾個全排列
Input
第一行有兩個整數 n 和 m 表示元素個數和詢問個數接下來 m 行,
如果輸入的字母為 P,接下來有一個整數 x,表示詢問第 x 個全排列如果輸入的字母為 Q,接下來有一個 n 元素的排列,表示詢問這是第幾個全排列
Output
對于 P?詢問,輸出一個 n?元素的排列。對于 Q?詢問,輸出一個整數 x
保證答案在 long long?范圍內
Example input
5 2
P 3
Q
1 2 5 3 4
Output
1 2 4 3 5
5
Hint
對于 20%的數據,n<=5,m<=20對于另外 20%的數據,n<=10,m<=100,且無操作 P
對于另外 20%的數據,n<=10,m<=100,且無操作 Q 對于 100%的數據,n<=20,m<=1000
改編自:P3014 [USACO11FEB]牛線Cow Line
?
今天才知道解決這個問題可以用到康托展開,不,可以說是今天才知道有康托展開這個東西
(一篇很好的講康托展開的博客:http://blog.csdn.net/acdreamers/article/details/7982067)
康托展開表示的是當前排列在n個不同元素的全排列中的名次。比如213在這3個數所有排列中排第3。
那么,對于n個數的排列,康托展開為:
其中表示第i個元素在未出現的元素中排列第幾。
舉個簡單易懂的例子:
對于排列4213來說,4在4213中排第3,注意從0開始,2在213中排第1,1在13中排第0,3在3中排第0,即:
?
,這樣得到4213在所有排列中排第ans=20
?
對于這道題,我們就可以利用康拓展開
#include<vector> #include<cstdio> #include<cstring> #include<cstdlib> #include<iostream> #include<algorithm> #define N 21000 #define ll long long using namespace std; char ch; bool vis[N]; ll x,s[N],ans,ans1[N],n,m,t,sum,v[N],str[N]; ll read() {ll x=0,f=1; char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1; ch=getchar();}while(ch>='0'&&ch<='9'){x=x*10+ch-'0'; ch=getchar();}return x*f; } ll work1(ll x) {memset(ans1,0,sizeof(ans1));for(int i=1;i<=n;i++)v[i]=i;for(int i=n;i>=1;i--){t=x/s[i-1];x%=s[i-1];t++;sort(v+1,v+1+n);ans1[n-i+1]=v[t];v[t]=N;}for(int i=1;i<=n;i++)printf("%lld ",ans1[i]); } int work2() {for(int i=1;i<=n;i++){sum=0;for(int j=i+1;j<=n;j++)if(str[j]<str[i]) sum++;ans+=s[n-i]*sum;}return ans++; } int main() {n=read(),m=read();s[0]=1;for(int i=1;i<=n;i++)s[i]=s[i-1]*i;while(m--){cin>>ch;if(ch=='P'){x=read();x--;work1(x);printf("\n");}else{ans=0;for(int i=1;i<=n;i++) str[i]=read();work2();printf("%lld\n",ans);}} } 康拓展開AC代碼?
走樓梯
Description
在你成功地解決了上一個問題之后,xxy?不禁有些氣惱,于是她在樓梯上跳來跳去,想要你求出她跳的方案數。..
xxy 站在一個?n 階樓梯下面,他每次可以往上跳一步或兩步,往下跳一步到三步(由于地心引力跳得比較遠),而且在往下跳的時候只能踩在往上跳時踩過的格子。
現在 xxy?在樓梯上亂跳,想問她跳到樓梯頂上最后又跳回樓梯下面的方案數 mod 2333333。
注意:xxy?只能一直向上跳,跳到樓梯最上面,然后再往下跳,跳回樓梯最底下。
Input
一個整數 n
Output
方案數 mod 2333333
Example
Input
5
Output
42
Hint
對于 10%的數據,n<=5對于 30%的數據,n<=10
對于 100%的數據,n<=1000000
改編自:U3357 C2-走樓梯
?
dp(詳細思路見:上一篇博文 T2 ?http://www.cnblogs.com/z360/p/7496500.html)
?
向下走可以看成向上走
?
f[i]表示第一次向上走到i,第二次向上也走到i的方案數
如果第二次向上走1步到i,這1步第一次有1種走法
如果第二次向上走2步到i,這2步第一次有2種走法
如果第二次向上走3步到i,這3步第一次有3種走法
如果第二次向上走4步到i,這4步第一次有5種走法
所以狀態轉移方程:f[i]=f[i-1]+f[i-2]*2+f[i-3]*3+f[i-4]*5
?
#include<cstdio> #include<cstring> #include<cstdlib> #include<iostream> #include<algorithm> #define N 11000000 #define mod 2333333 using namespace std; long long n,m,x,y,z,f[5],dp[N]; long long read() {long long x=0,f=1; char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1; ch=getchar();}while(ch>='0'&&ch<='9'){x=x*10+ch-'0'; ch=getchar();}return x*f; } int main() {n=read();f[0]=1;dp[0]=1;for(int i=1;i<=4;i++)for(int j=1;j<=2;j++)if(i-j>=0) f[i]+=f[i-j];else break;for(int i=1;i<=n;i++)for(int j=1;j<=4;j++)if(i-j>=0) dp[i]=(dp[i]+dp[i-j]*f[j])%mod;else break;printf("%lld\n",dp[n]);return 0; } 洛谷AC代碼 m=4時 #include<cstdio> #include<cstring> #include<cstdlib> #include<iostream> #include<algorithm> #define N 11000000 #define mod 2333333 using namespace std; long long n,m,x,y,z,f[4],dp[N]; long long read() {long long x=0,f=1; char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1; ch=getchar();}while(ch>='0'&&ch<='9'){x=x*10+ch-'0'; ch=getchar();}return x*f; } int main() {n=read();f[0]=1;dp[0]=1;for(int i=1;i<=3;i++)for(int j=1;j<=2;j++)if(i-j>=0) f[i]+=f[i-j];else break;for(int i=1;i<=n;i++)for(int j=1;j<=3;j++)if(i-j>=0) dp[i]=(dp[i]+dp[i-j]*f[j])%mod;else break;printf("%I64d\n",dp[n]);return 0; } 改編題代碼 m=3時?
部落
Description
很久很久以前,有一個島,島上有 n?個人,人們經常爆發戰爭。經 xxy?研究發現,如果兩個人住的越近,那么他們之間爆發戰爭的可能性就越大。Xxy?還發現,如果將某些人按居住地劃分為 k?個部落,那么部落內部的人們為了部落的強大便不會發生戰爭。這就意味著,劃分為 k?個部落后,不同的部落的人住的越近,爆發戰爭的可能性就越大。設 d?為任意兩個不同部落的人之間的歐幾里得距離,xxy?想知道在爆發戰爭可能性最小的情況下,最小的 d?是多少。
注:歐幾里得距離即平面上兩個點的距離
Input
第一行兩個整數 n,k。
接下來 n?行,每行兩個整數 x,y?表示第 i?個人的坐標
Outpu
最小的 d,保留 2?位小數
Example
?
| ? | people.in | people.out |
| ? | ? | ? |
| 4 | 2 | 1.00 |
| 0 | 0 | ? |
| 0 | 1 | ? |
| 1 | 1 | ? |
| 1 | 0 | ? |
?
?
?
Hint
30%的數據,k<=n<=10
50%的數據,k<=n<=100
100%的數據,k<=n<=1000,0<=x<=100000,0<=y<=10000
?
這真是道大水題,可是蒟蒻在考試的時候沒想出來、、、
使這幾個部落劃分成m個部落的最小邊不就是他最小生成樹中要添加的第n-m條邊嗎????
要將這n各部落全部連接起來需要n-1條邊,我們要將它劃分成m個部落,也就是說我們要有m個部落不能被連接起來,我們要先將距離小的兩個部落先連起來,這就恰好是最小生成樹的思想,所以要想到最小生成樹也不難。我們將這m個部落連起來恰好是用m-1條邊,也就是說我們將除了那m個部落連起來,恰好是要用n-1-(m-1)也就是n-m條邊,然后這m部落間的最小的距離就是n-m+1條邊的長度了
#include<cmath> #include<cstdio> #include<cstring> #include<cstdlib> #include<iostream> #include<algorithm> #define N 1100 using namespace std; double z,ans; int n,m,s,x,y,fx,fy,sum,xx[N],yy[N],fa[N]; int read() {int x=0,f=1; char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1; ch=getchar();}while(ch>='0'&&ch<='9'){x=x*10+ch-'0'; ch=getchar();}return x*f; } struct Edge {int x,y;double z; }edge[N*N]; int cmp(Edge a,Edge b) {return a.z<b.z; } int find(int x) {if(fa[x]==x) return x;fa[x]=find(fa[x]);return fa[x]; } int main() {n=read(),m=read();for(int i=1;i<=n;i++) xx[i]=read(),yy[i]=read();for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)if(i!=j) {s++;z=sqrt((double)pow(xx[i]-xx[j],2)+(double)pow(yy[i]-yy[j],2));edge[s].x=i;edge[s].y=j;edge[s].z=z;}for(int i=1;i<=n;i++) fa[i]=i;sort(edge+1,edge+1+s,cmp);for(int i=1;i<=s;i++){x=edge[i].x,y=edge[i].y;fx=find(x),fy=find(y);if(fa[fx]==fy) continue;fa[fx]=fy;sum++;if(sum==n-m+1) {ans=edge[i].z; break;}}printf("%.2lf",ans);return 0;} 最小生成樹、、轉載于:https://www.cnblogs.com/z360/p/7496680.html
總結
- 上一篇: MacCormack差分格式的全局误差分
- 下一篇: webdriver-helper安装说明