Problem4:题意:有n个人站队,个子高的会挡住格子矮(或者和他一样高的)的,问有多少种站队方式使得从队头看去恰好能看到k个人?
今天的题目感觉是水题集合OTZ,可惜木有人屠场。。
dp
我们发现如果一个一个把个子高的添加进去会出现转移的问题
然后ORZ ymx神犇
正难则反
从大到小sort
然后发现每放入一个最小值只和他的最前面的最小值有关,如果不放在第一个的话就永远被挡住了T^T
然后用dp[i][j][k]表示前i个人站队然后能看到j个人,最开头那一只是k
然后转移就不多说了=-=
Em,下面我们介绍一种特殊的做法:
第一类Stirling数的定义是
From百度百科
同样第一类Stirling数同样也可以构成一个三角,可以由此分析其性质。
无符号Stirling数 | 有符号Stirling数 | |
n=0 | 1 | 1 |
n=1 | 0 1 | 0 1 |
n=2 | 0 1 1 | 0 -1 1 |
n=3 | 0 2 3 1 | 0 2 -3 1 |
n=4 | 0 6 11 6 1 | 0 -6 11 -6 1 |
n=5 | 0 24 50 35 10 1 | 0 24 -50 35 -10 1 |
n=6 | 0 120 274 225 85 15 1 | 0 -120 274 -225 85 -15 1 |
n=7 | 0 720 1764 1624 735 175 21 1 | 0 720 -1764 1624 -735 175 -21 1 |
#include
#include
#include
#include
#define maxn 210
using namespace std;
typedef long long ll;
const ll mod = 1000000007ll;
int n, K;
ll dp[maxn][maxn][maxn];
int a[maxn];
bool cmp(const int& a, const int& b){return a > b;}
void upd(ll& a, ll b){
a = a + b;
if(a >= mod)a -= mod;
}
int main(){
freopen("palace.in", "r", stdin);
freopen("palace.out", "w", stdout);
scanf("%d%d", &n, &K);
for(int i = 1; i <= n; i ++)
scanf("%d", &a[i]);
sort(a+1, a+1+n, cmp);
dp[1][1][1] = 1;
for(int i = 1; i <= n; i ++){
int now = a[i+1];
for(int j = 1; j <= i; j ++){
for(int k = 1; k <= i; k ++){
if(now == a[k]){
upd(dp[i+1][j][i+1], dp[i][j][k]);
upd(dp[i+1][j][k], dp[i][j][k] * i % mod);
}
else{
upd(dp[i+1][j+1][i+1], dp[i][j][k]);
upd(dp[i+1][j][k], dp[i][j][k] * i % mod);
}
}
}
}
ll ans = 0;
for(int i = 1; i <= K; i ++)
for(int j = 1; j <= n; j ++)
upd(ans, dp[n][i][j]);
printf("%lld\n", ans % mod);
return 0;
}
Problem2 :位运算
给定N,K,L,M,求在长度为N,每个元素在[0,2^L)的数组中,(a1 and a2)or(a2 and a3)or … or(a(n-1) and an)=K的数组有多少个
Source: CF551D
最关键最关键的是按位考虑QAQ!!!
我想了30min!!
然后就没有然后了
喔对!!
然后你千万不要用unsigned long long做减法
千万不要!!
#include
#include
#include
#include
using namespace std;
typedef unsigned long long ll;
ll n, k, l, m;
struct Matrix{
ll a[2][2];
void clear(){memset(a, 0, sizeof a);}
void set(){clear();a[0][0] = a[1][1] = 1;}
}mat, ans;
const int N = 2;
Matrix operator*(const Matrix& a, const Matrix& b){
Matrix c;c.clear();
for(int i = 0; i < N; i ++)
for(int j = 0; j < N; j ++)
for(int k = 0; k < N; k ++)
c.a[i][j] = (c.a[i][j] + a.a[i][k] * b.a[k][j]) % m;
return c;
}
ll power_mod(ll b){
//cout << b << endl;
mat.a[0][0] = mat.a[1][0] = mat.a[0][1] = 1;
ans.set();
while(b){
if(b & 1)ans = ans * mat;
b >>= 1;
mat = mat * mat;
}
mat.clear();
mat.a[0][1] = 1, mat.a[0][0] = 1;
ans = mat * ans;
// cout << ans.a[0][0] << endl;
return ans.a[0][0];
}
ll power_mod_num(ll a, ll b){
ll ret = 1;
while(b){
if(b & 1)ret = ret * a % m;
b >>= 1;
a = a * a % m;
}
return ret % m;
}
long long dcrs(long long a, long long b){
long long t = (a - b) % (long long)m;
if(t < 0) t += m;
return t;
}
int main(){
freopen("binary.in", "r", stdin);
freopen("binary.out", "w", stdout);
cin >> n >> k >> l >> m;
//No Solution
if(l == 0 && k){printf("0"); return 0;}
//if(l == 0 && k == 0){printf("1"); return 0;}
ll test = 1ull << l;test --;
if(test == 0)test --;
if(test < k){printf("0"); return 0;}
//Solve
int L = l;
ll a0 = power_mod(n) % m;//Matrix_for_Fibonacci
ll a1 = dcrs(power_mod_num(2, n), a0) % m;//total - Fibo
ll ans = 1;
for(int i = 1; i <= l; i ++){
if(k & 1)ans = ans * a1 % m;
else ans = ans * a0 % m;
k >>= 1;
}
cout << ans % m << endl;
return 0;
}