Yali7月集訓Contest2 T1 Cube 題解
阿新 • • 發佈:2018-07-07
是我 define 基礎 for 數字 test printf 發現 st2
題目鏈接:
連我們都只有紙質題目...話說雅禮集訓都是這樣的嗎...
大意
0維基本圖形是一個點
1維基本圖形是一條線段
2維基本圖形是一個正方形
3維基本圖形是一個正方體
4維基本圖形是...
求\(n\)維基礎圖形中有多少個\(m\)維基礎圖形\((n>=m)\)並對\(998244353\)取模
分析
手玩樣例打表吼啊
當然還是要暗中觀察一下啦
線段變成正方形,點數變為原來兩邊,邊數除了變為原來兩倍之外還要加上原來點數所對應連起來的邊
正方形變正方體也類似
於是我就yy出一個遞推式\(num[x][m]=num[x-1][m]*2+num[x-1][m-1]\)
\(num[x][m]\)
然後我們可以打一張表
然後就有dalao發現了規律(我比較傻考場上都手玩出每一項能整除2的冪都沒發現規律)
\(num[n][m]/2^{n-m}=C^n_m\)
然後就ok了
註意
在訂正這道題時發現幾個值得註意的地方
線性求逆元時我原來的方法不行
原來我這麽線性求逆元
inv[i]=(-(p/i)*inv[p%i]%p);
結果我發現數字一大就GG了
這是大佬的線性求逆元
inv[i]=(ll)(p-(p/i))*inv[p%i]%p;
這就很穩了
一個有趣的性質
逆元的階乘是原來數字階乘的逆元
很有趣,好象可證
代碼:
#include <iostream> #include <cstdio> #include <cstdlib> #include <algorithm> #include <cstring> #include <cctype> #include <map> #define ri register int #define ll long long using namespace std; const int maxn=100005; const int inf=0x7fffffff; const int p=998244353; template <class T>inline void read(T &x){ x=0;int ne=0;char c; while(!isdigit(c=getchar()))ne=c==‘-‘; x=c-48; while(isdigit(c=getchar()))x=(x<<3)+(x<<1)+c-48; x=ne?-x:x; return ; } int inv[maxn],twopow[maxn],fac[maxn]; inline void pre(){ inv[0]=inv[1]=1,fac[1]=1,twopow[0]=1,twopow[1]=2; for(ri i=2;i<=100002;i++){ fac[i]=(ll)fac[i-1]*i%p; inv[i]=(ll)(p-(p/i))*inv[p%i]%p; twopow[i]=(ll)(twopow[i-1]<<1)%p; //cout<<fac[i]<<‘ ‘<<inv[i]<<‘ ‘<<twopow[i]<<endl; } for(ri i=2;i<=100002;i++){ inv[i]=(ll)inv[i]*inv[i-1]%p;//比較神奇,逆元的階乘是原來數的階乘的逆元 } return ; } int t; inline int solve(int m,int n){ if(m==0)return twopow[n]; if(n==m)return 1; return (ll)fac[n]*inv[n-m]%p*twopow[n-m]%p*inv[m]%p; } int main(){ int n,m; read(t); pre(); while(t--){ read(n),read(m); printf("%d\n",solve(m,n)); } return 0; }
Yali7月集訓Contest2 T1 Cube 題解