生活随笔
收集整理的這篇文章主要介紹了
2017-9-13 NOIP模拟赛[xxy]
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
全排列
(permutation.cpp/c/pas)
Description
從 n 個不同元素中任取 m(m≤n)個元素,按照一定的順序排列起來,叫做從 n
個不同元素中取出 m 個元素的一個排列。當 m=n 時所有的排列情況叫全排列。
你覺得 xxy 會問你全排列的個數嗎?Xxy:這個問題能淹死你,我才不問呢。我
要問的是求 n 的全排列中,先遞增后遞
減、先遞減后遞增的全排列的個數。由于答案可能很大,對 p 取余
Input
輸入包含多組測試數據每組測試
數據一行兩個整數 n,p
Output
對于每組測試數據輸出一行表示答案
Example
permutation.in permutation.out
3 5 4
2 233 0
Hint
設數據組數為 T
對于 10%的數據,n<=10,p<=1000,T=1
對于另外 10%的數據,n<=12,p<=1000,T<=12
對于另外 10%的數據,n<=100,p<=100000,T<=100
對于另外 10%的數據,n<=100000,p<=1000000,T=1
對于另外 10%的數據,n<=100000,p<=1000000,T<=1000
對于另外 20%的數據,n<=1e9,p<=1e9,T<=1000
對于 100%的數據,n<=1e18,p<=1e18,T<=1000
/*打表找規律Ans=2^n-4用快速冪和快速乘進行計算
*/
#include<iostream>
#include<cstdio>
using namespace std;
long long n,p;
long long mul(
long long a,
long long b){long long res=
0;while(b){if(b&
1)res=(res+a)%
p;a=(a+a)%
p;b>>=
1;}return res;
}
long long pow(
long long a,
long long b){long long res=
1;while(b){if(b&
1)res=
mul(res,a);a=
mul(a,a);b>>=
1;}return res;
}
int main(){//freopen("Cola.txt","r",stdin);freopen(
"permutation.in",
"r",stdin);freopen("permutation.out",
"w",stdout);while(cin>>n>>
p){if(n==
1||n==
2){printf("0\n");continue;}long long ans=pow(
2,n);cout<<(ans-
4+p)%p<<
endl;}
} 100分 打表找規律 ?
埃及分數
(egypt.cpp/c/pas)
Description
對于一個分數 a/b(a!=1),將它表示為 1/x + 1/y + 1/z ……的形式,x,
y,z……互不相同。
多解取加數少的。加數相同時,取最小的分數最大的,最小分數相同時,取次小分
數最大的,以此類推。
輸入保證 a<b 且 gcd(a,b)=1
Input
輸入包含多組測試數據每組測試數
據包含一行 2 個數 a,b
Output
對于每組測試數據,輸出一行表示答案,只輸出分母,每個分母之間空 1 格
從小到大輸出
Example
egypt.in egypt.out
5 6 2 3
8 9 2 3 18
Hint
對于 10%的數據,a,b<=10
對于另外 10%的數據,a,b<=100
對于另外 20%的數據,a,b<=10000
對于另外 30%的數據,a,b<=100000
對于 100%的數據,a,b<=1000000
由于本題時間復雜度不隨數據范圍的遞增而遞增,在此給出 std 耗時:
30% <=0.01s
10% <=0.2s
40% <=0.5s
20% <=0.9s
/*迭代加深搜索剪枝有一個非常重要的剪枝,當搜到深度為dep時,還有maxd-d+1的搜索空間如果每次都減一個1/i那么就是減delta=(1/i)*(maxd-d+1)如果(aa/bb)-delta>0就返回
*/
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int a,b,maxd;
long long ans[
10010],v[
10010];
int get_first(
int x,
int y){for(
int i=
1;;i++
)if(x*i>=y)
return i;
}
bool better(
int d){for(
int i=d;i>=
0;i--
)if(ans[i]!=v[i])
return ans[i]==-
1||ans[i]>
v[i];return false;
}
long long gcd(
long long x,
long long y){if(y==
0)
return x;return gcd(y,x%
y);
}
bool dfs(
int dep,
int from,
long long aa,
long long bb){if(dep==
maxd){if(bb%aa)
return false;v[dep]=bb/
aa;if(better(dep))
for(
int i=
0;i<=dep;i++)ans[i]=
v[i];return true;}bool ok=
false;from=max(
from,get_first(aa,bb));for(
int i=
from;;i++
){if(aa*i>=bb*(maxd-dep+
1))
break;v[dep]=
i;long long b2=bb*i,a2=aa*i-bb,g=
gcd(b2,a2);if(dfs(dep+
1,i+
1,a2/g,b2/g)) ok=
true;}return ok;
}
int main(){freopen("egypt.in",
"r",stdin);freopen("egypt.out",
"w",stdout);scanf("%d%d",&a,&
b);int fr=
get_first(a,b);for(maxd=
1;;maxd++
){memset(ans,-
1,
sizeof(ans));if(dfs(
0,fr,a,b)){for(
int i=
0;i<=maxd;i++)printf(
"%d ",ans[i]);return 0;}}return 0;
} 100分 迭代加深搜索+剪枝 ?
走樓梯
(stair.cpp/c/pas)
Description
由于經典走樓梯問題被 xxy 升級了 2 次,上帝非常滿意,所以當 xxy 完成這最
后一次跳躍時,會有一定的幾率開啟輪回之梯。輪回之梯有 n 階,每一階上都會有一個
輪回指數,xxy 用不同的策略走到輪回之梯的第 n 階,會得到不同的輪回值。
由于輪回之梯不是普通的樓梯,每走一步需要消耗極大的體力,xxy 體力有限。上
帝允許 xxy 在中途休息。所以 xxy 如果在第 i 階,他可以選擇立刻走到第 i+1 階,也可
以選擇在第 i 階休息一會兒。休息和立刻走看做不同的走樓梯方式。
上帝說:我現在給你提供所有臺階的輪回指數,我需要你回答所有不同的走輪回之
梯的方式獲得的輪回值之和。如果某種方式你算不出來,你可以親自去走一遍。你走的次數
越少,就會有越大的幾率開啟六道輪回。Xxy 非常想開啟六道輪回,但由于之前在樓梯上跳
來非常累,現在不想動彈,連飛也不想飛。所以只能在求助學信息學奧賽的你了。
輪回值計算方式:
輪回值為所有的輪回子值之和。
設第 i 個臺階的輪回指數為 xi,如果 xxy 連續從第 L 階走到第 R 階,那么
xxy 可以得到的輪回子值為 xL 一直累乘到 xR。特別的,當 L=R 時,輪回子值為 xL。
注意:xxy 開始在輪回之梯的第 1 階,可以選擇先休息一會兒,也可以立刻走到
第 2 階。走一遍輪回之梯指的是從第 1 階走到第 n 階。
由于答案很大,上帝可不想看到幾千幾百個數字,所以你只需要告訴他答案對
1000000007 取模。
Input
第一行一個整數 n。
接下來 n 個整數,表示 xi
Output
輸出一行表示答案
Example
stair.in stair.out
2 30
1 2 4
Hint
對于 10%的數據,1<=n<=10,1<=xi<=10
對于另外 20%的數據,所有的 Xi=1
對于另外 20%的數據,n<=100,xi<=1e5
對于另外 20%的數據,n<=1000,xi<=1e5
對于 100%的數據,n<=100000,xi<=1e9
/*DpDp[i][j]已經枚舉了i個數,插入了j個加號
*/
#include<cstdio>
#include<cstring>
#include<iostream>
#define mod 1000000007
using namespace std;
int n,a[
100001];
long long cf[
100001];
long long dp[
100001],pre[
100001],inv[
100001];
long long pow(
long long a,
long long b){long long res=
1;while(b){if(b&
1) res*=a,res%=
mod;b>>=
1; a*=a; a%=
mod; }return res;
}
void read(
int &
x){x=
0;
char c=
getchar();while(!isdigit(c)) c=
getchar();while(isdigit(c)) { x=x*
10+c-
'0'; c=
getchar(); }
}
int main(){freopen("stair.in",
"r",stdin);freopen("stair.out",
"w",stdout);read(n);for(
int i=
1;i<=n;i++
) read(a[i]);cf[0]=
1; for(
int i=
1;i<=n;i++) cf[i]=cf[i-
1]*
2%
mod;long long tot;pre[0]=
1;for(
int i=
1;i<=n;i++) pre[i]=pre[i-
1]*a[i]%
mod;for(
int i=
1;i<=n;i++) inv[i]=pow(pre[i],mod-
2);long long sum1=
0,sum2=
1;for(
int i=
1;i<=n;i++
){dp[i]=(sum1+sum2*pre[i]%mod)%
mod;sum1=(sum1+dp[i])%
mod;sum2=(sum2+cf[i-
1]*inv[i]%mod)%
mod;} printf("%I64d",dp[n]);
} 100分 前綴和優化dp ?
轉載于:https://www.cnblogs.com/thmyl/p/7515161.html
總結
以上是生活随笔為你收集整理的2017-9-13 NOIP模拟赛[xxy]的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。