題目描述給出整數n, 則集合s包含整數1, 2, 3, ... , n。考慮s的某個非空子集t,把子集t的所有元素都寫下來,如果使用0-9中每個數字的次數都沒有超過1次(允許是0次),則把子集t稱為酷子集。
例如,子集 和 都是酷子集,而 不是,因為數字4使用了2次。同理,也不是酷子集。
輸入格式
第1行:1個整數n(1≤n≤10^9),表示集合s的元素個數。
輸出格式
第1行:1個整數,表示答案,答案模1e9+7。
輸入樣例 10
輸出樣例
767樣例說明
n=10的所有非空子集有2^10-1=1023個。不是酷子集的情況是同時包含1和10,這類子集一共有2^8 =256個,所以答案是1023-256=767。
題解 by zjx
對於所有滿足條件的集合,每個數字最多出現一次,而總共有10個數字,可以考慮列舉這10個數字的狀態。
設f[s]表示所用的數字集合是s且集合中所有數均不超過n的方案總數。考慮s的乙個子集v,用v組成乙個數,s-v組成其餘的數。
記n有p位:
1.如果|v|2.如果|v|=p,那麼我們一位一位考慮。
①對於某一位k,如果這一位放了乙個小於n這一位的數(當然第一位不能放0),之後的數可以任意排列,方案數為(p-k)!;
②否則我們在這裡放置和原數這一位一樣的數(前提是這些數中有),繼續處理k+1位;
③特別的,如果v完全等於n,答案需要加上1。算出v的方案數後,與f[s-v]相乘即為答案。
3.如果|v|>p,直接賦0。
最後把所有的f[1]~f[2^10-1]加起來就是答案了
#includeconst int mod=1e9+7;
const int n=15;
const int m=(1<<10)+5;
int n, ncnt, note[10];
void prep_digit()
int fac[n], inv[n];
void prep_fi()
for( int i=2; i<=10; i++ ) inv[i]=1ll*inv[i]*inv[i-1]%mod;
}int f[m], bcnt[m], jud, scnt;
void prep_situ() {
scnt=(1<<10);
for( int s=0; s>1]+(s&1);//記錄當前集合包含幾個數
if( bcnt[s]>ncnt ) f[s]=0;//比n的位數多
else if( bcnt[s]
noip模擬賽 密碼
表示沒看懂演算法3 問題描述 有壓迫,就有反抗。mored的寵物在法庭的幫助下終於反抗了。作為乙隻聰明的寵物,他打算把魔法使mored的魔法書盜去,奪取mored的魔法能力。但mored怎麼會讓自己的魔法書輕易地被盜取?mored在魔法書上設定了乙個密碼鎖,密碼鎖上有乙個問題。施以斯臥鋪魔法吧,你有...
NOIP模擬賽 老師
題目描述 一座有n層的教學樓裡有一些學生,第i 0 i n 層有studentsi個學生。你被給定了乙個數k,如果第i層有x個學生,那麼這一層需要 x k 個老師。你可以調整每個學生的樓層,但是每個學生至多只能調整一層,就是說第i層的學生只能去第i 1層 如果有的話 第i層 第i 1層 如果i 1 ...
NOIP模擬賽 分錢
題目描述 兩個人在街上撿到了一些錢,這些錢共有n張,他們等了很久也沒有等來失主,於是決定把錢平分。但錢可能無法平分。他們先把能夠平分的錢盡量先平分了,使得剩下不能平分的錢盡量少。這些不能平分的錢怎麼辦呢他?他們決定拿去賭場裡面賭一把。他們運氣太好了,那些不能平分的錢變成了雙倍,於是他們就把那個錢分了...