Good Bye 2018 D. New Year and the Permutation Concatenation
https://www.cnblogs.com/violet-acmer/p/10201535.html
题意:
求 n 的所有全排列组成的序列中连续的 n 个数加和为 n*(n+1)/2 的区间个数。
题解:
n 最大为1e6,而n的全排列个数为 n! ,一共有 n*n!个数,存都存不下啊......
然后,第一反应就是,这题是找规律的。
一言不合就打表
==========
i=1
1
==========
i=2
2
==========
i=3
9
==========
i=4
56
==========
i=5
395
==========
i=6
3084
==========
i=7
26621
起初,想到了数 n 有 n! 个全排列,那么,这 n! 个全排列肯定满足条件,那么剩下的情况呢?
i=3 : 9=3!+3...........................3=3*1=3*(2-1);
i=4 : 56=4!+32.......................32=4*8=4*(9-1);
i=5 : 395=5!+275 ..................275=5*55=5*(56-1);
仔细观察一下括号中的2,9,56,相信这个规律很好找吧..........
AC代码:
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<cstring> 5 using namespace std; 6 #define ll __int64 7 #define mem(a,b) memset(a,b,sizeof(a)) 8 const ll MOD=998244353; 9 const int maxn=1e6+10; 10 11 int n; 12 ll a[maxn]; 13 14 int main() 15 { 16 cin>>n; 17 a[1]=1; 18 ll fact=1;//阶乘 19 for(int i=2;i <= n;++i) 20 { 21 fact=fact*i%MOD; 22 a[i]=fact+i*(a[i-1]-1); 23 a[i] %= MOD; 24 } 25 cout<<a[n]<<endl; 26 }
打表找规律代码:
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 using namespace std; 5 const int maxn=1e6; 6 7 int p[maxn]; 8 int b[maxn]; 9 10 int main() 11 { 12 for(int i=1;i <= 6;++i) 13 { 14 for(int j=0;j < i;++j) 15 b[j]=j+1; 16 17 int index=1; 18 do 19 { 20 for(int j=0;j < i;++j) 21 p[index++]=b[j]; 22 }while(next_permutation(b,b+i)); 23 int res=0; 24 for(int j=1;j+i <= index;++j) 25 { 26 int sum=0; 27 for(int k=j;k < j+i;++k) 28 sum += p[k]; 29 30 if(sum == i*(i+1)/2) 31 res++; 32 } 33 printf("==========\ni=%d\n",i); 34 printf("%d\n",res); 35 } 36 }
用到了一个骚操作:next_permutation();
爽歪歪,哈哈哈