全排列
(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
题解:打表找规律+快速幂+快速乘
规律可得
n=3,ans=4.
n=4,ans=12
n=5,ans=28
所以ans=2^n-4.
代码
#include<iostream> #include<cstdio> using namespace std; long long n,p; long long mul(long long x,long long y){ long long ans=0,now=x; while(y){ if(y&1){ ans=(ans+now)%p; } now=(now+now)%p; y>>=1; } return ans; } long long pow(long long x,long long y){ long long now=x,ans=1; while(y){ if(y&1)ans=mul(ans,now),ans%=p; now=now*now%p; y>>=1; } return ans; } int main(){ while(cin>>n>>p){ if(n==1||n==2){ printf("0\n"); continue; } cout<<(pow(2,n)-4+p)%p; } return 0; }
埃及分数
(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
题目大意:迭代加深搜索
代码:
int main(){ int a,b; int rnd=0; while(~scanf("%d%d",&a,&b)){ int ok=0; for(maxd=1;;maxd++){ memset(ans,-1,sizeof(ans)); if(dfs(0,get_first(a,b),a,b)){ ok=1;break; } } } return 0; } int get_first(int x,int y){ int res=y/x; return res*x>=y?:res:res+1; } ll gcd(ll a,ll b){ return b==0?a:gcd(b,a%b); } bool better(int d){ for(int i=d;i>=0;i--) if(v[i]!=ans[i]) return ans[i]==-1||v[i]<ans[i]; return false; } bool dfs(int d,int from,ll aa,ll bb){ if(d==maxd){ if(bb%aa)return false; v[d]=bb/aa; if(better(d))memcpy(ans,v,sizeof (ll)*(d+1)); return true; } bool ok=true; from=max(from,get_first(aa,bb)); for(int i=from;;i++){ if(bb*(maxd+1-d)<=i*aa)break;v[d]=i; } }