日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

9.6 模拟试题

發布時間:2023/12/18 编程问答 24 豆豆
生活随笔 收集整理的這篇文章主要介紹了 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

總結

以上是生活随笔為你收集整理的9.6 模拟试题的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。