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;
}