比賽時一直以爲是個組合數找規律的題,今天一想應該要用dp,推了一節毛概課,到晚上終於給A了。
dp[i][j]表示當第i輪有j個不同的時的方案數,那麼可以得到初始條件dp[0][num]=1(num表示一開始有多少個燈狀態不同,因爲接下來遞推要用乘法所以初始化爲1,這裏只需知道dp[0][num]是初始條件即可)
那麼dp[i][j]可以怎麼得到呢?
首先肯定是從第i-1輪得到,這時假設第i-1輪有p個燈的狀態不同,第i輪要有j個燈的狀態不同,那麼怎麼從p到j呢?
可以從p中選擇x個變換,從n-p(即相同狀態的燈)中選擇y個變換,當然x,y不能隨便選,因爲一輪要變換k個,所以首先x+y==m,還有從p個不同的狀態到j個不同的狀態還要滿足p-x+y==j,
這時列一個二元一次方程組,即可得到y=(j+m-p)/2,這時還要滿足y是整數。所以x爲 m-y。
所以可以得出狀態轉移方程 dp[i][j]+=(dp[i-1][p]*C(p,x)%mod*C(n-p,y)%mod)%mod.
求組合數要用楊輝三角求,,否則會超時。。。
還要注意所有地方都要注意取模
#include<bits/stdc++.h>
#define exp 1e-8
#define mian main
#define pii pair<int,int>
#define pll pair<ll,ll>
#define ll long long
#define pb push_back
#define PI acos(-1.0)
#define inf 0x3f3f3f3f
#define w(x) while(x--)
#define int_max 2147483647
#define lowbit(x) (x)&(-x)
#define gcd(a,b) __gcd(a,b)
#define pq(x) priority_queue<x>
#define ull unsigned long long
#define sc(x) scanf("%d",&x)
#define scl(x) scanf("%lld",&x)
#define pl(a,n) next_permutation(a,a+n)
#define ios ios::sync_with_stdio(false)
#define met(a,x) memset((a),(x),sizeof((a)))
using namespace std;
const int N=110;
const int mod=998244353;
ll dp[N][N]; //dp[i][j] 第i輪有j個不同時的方案數
char a[N],b[N];
int n,m,k;
ll c[N][N];
void init()
{
c[1][1]=1;
c[0][0]=1;
c[1][0]=1;
for(int i=2;i<=110;i++){
c[i][0]=1;
for(int j=1;j<=i;j++)
c[i][j]=(c[i-1][j]+c[i-1][j-1])%mod;
}
}
int main()
{
int t;
scanf("%d",&t);
init();
while(t--){
scanf("%d%d%d",&n,&k,&m);
scanf("%s%s",&a,&b);
int num=0;
for(int i=0;i<n;i++)
if(a[i]!=b[i])
num++;
met(dp,0);
dp[0][num]=1;// 初始化
for(int i=1;i<=k;i++){
for(int j=0;j<=n;j++){
for(int p=0;p<=n;p++){ //上一輪有p個不同
if(j+m-p<0)
break;
if((j+m-p)%2)
continue;
int y=(j+m-p)/2; //要滿足的條件
int x=m-y; //從p中拿x個,n-p中拿y個
if(x>p||y>n-p||x<0)
continue;
dp[i][j]+=(dp[i-1][p]*c[p][x]%mod*c[n-p][y]%mod)%mod;
dp[i][j]%=mod;
}
}
}
printf("%lld\n",dp[k][0]%mod);
}
}
這時n三次方的複雜度即可過。
暴力貪心,比賽時沒想到這麼貪也能過,以爲會T......就沒有寫
應該是沒有給特別大的數據,正解應該用到了優先隊列優化成nlogn。
#include<bits/stdc++.h>
#define exp 1e-8
#define mian main
#define pii pair<int,int>
#define pll pair<ll,ll>
#define ll long long
#define pb push_back
#define PI acos(-1.0)
#define inf 0x3f3f3f3f
#define w(x) while(x--)
#define int_max 2147483647
#define lowbit(x) (x)&(-x)
#define gcd(a,b) __gcd(a,b)
#define pq(x) priority_queue<x>
#define ull unsigned long long
#define sc(x) scanf("%d",&x)
#define scl(x) scanf("%lld",&x)
#define pl(a,n) next_permutation(a,a+n)
#define ios ios::sync_with_stdio(false)
#define met(a,x) memset((a),(x),sizeof((a)))
using namespace std;
const int N=1e5+10;
int n,ans;
struct node
{
int l,r;
}a[N];
bool cmp(node x,node y)
{
if(x.l==y.l)
return x.r<y.r;
return x.l<y.l;
}
int main()
{
int t;
scanf("%d",&t);
while(t--){
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%d%d",&a[i].l,&a[i].r);
sort(a+1,a+1+n,cmp);
map<int,int>mp;
mp.clear();
ans=0;
for(int i=n;i>=1;i--){
for(int j=a[i].r;j>=a[i].l;j--){
if(mp[j]==0){
mp[j]=1;
ans++;
break;
}
}
}
printf("%d\n",ans);
}
}
思路:
當輸入的兩個點相等時,全輸出0,當有環的時候也輸出全是0
拓撲排序判環,在對於每一個點正向搜索小於它的點,反向搜大於它的點,對於這些點只要滿足num1[i]<=n/2 &&num2[i]<=n/2, 即可,對於不同連通圖中的點不需要考慮
#include<bits/stdc++.h>
#define exp 1e-8
#define mian main
#define pii pair<int,int>
#define pll pair<ll,ll>
#define ll long long
#define pb push_back
#define PI acos(-1.0)
#define inf 0x3f3f3f3f
#define w(x) while(x--)
#define int_max 2147483647
#define lowbit(x) (x)&(-x)
#define gcd(a,b) __gcd(a,b)
#define pq(x) priority_queue<x>
#define ull unsigned long long
#define sc(x) scanf("%d",&x)
#define scl(x) scanf("%lld",&x)
#define pl(a,n) next_permutation(a,a+n)
#define ios ios::sync_with_stdio(false)
#define met(a,x) memset((a),(x),sizeof((a)))
using namespace std;
const int N=110;
int head[N],rhead[N];
int num1[N],num2[N];
int in1[N];
int n,m,tot1,tot2;
bool vis[N];
struct node
{
int ne,v;
}e[N*N],re[N*N];
bool tuopu()//еп╩╥
{
queue<int>q;
for(int i=1;i<=n;i++)
if(in1[i]==0)
q.push(i);
int cnt=0;
while(!q.empty()){
int u=q.front();
q.pop();
cnt++;
for(int i=head[u];i;i=e[i].ne){
int v=e[i].v;
in1[v]--;
if(in1[v]==0)
q.push(v);
}
}
return cnt==n;
}
void bfs2()
{
queue<int>que;
for(int i=1;i<=n;i++){
met(vis,0);
que.push(i);
int ans=0;
while(!que.empty()){
int u=que.front();
que.pop();
for(int j=head[u];j;j=e[j].ne){
int x=e[j].v;
if(vis[x])
continue;
ans++;
que.push(x);
vis[x]=1;
}
}
num1[i]=ans;
}
}
void bfs()
{
queue<int>que;
for(int i=1;i<=n;i++){
met(vis,0);
que.push(i);
int ans=0;
while(!que.empty()){
int u=que.front();
que.pop();
for(int j=rhead[u];j;j=re[j].ne){
int x=re[j].v;
if(vis[x])
continue;
ans++;
que.push(x);
vis[x]=1;
}
}
num2[i]=ans;
}
}
void add1(int x,int y)
{
e[++tot1].ne=head[x];
e[tot1].v=y;
head[x]=tot1;
}
void add2(int x,int y)
{
re[++tot2].ne=rhead[x];
re[tot2].v=y;
rhead[x]=tot2;
}
int main()
{
int t;
scanf("%d",&t);
while(t--){
int x,y;
scanf("%d%d",&n,&m);
tot1=0;
tot2=0;
for(int i=0;i<=n;i++){
num1[i]=0;
num2[i]=0;
head[i]=0;
rhead[i]=0;
in1[i]=0;
}
bool flag=false;
for(int i=1;i<=m;i++){
scanf("%d%d",&x,&y);
if(x==y)
flag=true;
add1(x,y);
add2(y,x);
in1[y]++;
}
if(flag){
for(int i=1;i<=n;i++)
printf("0");
printf("\n");
continue;
}
if(tuopu()){
bfs2();
bfs();
for(int i=1;i<=n;i++){
if(num1[i]<=n/2&&num2[i]<=n/2)
printf("1");
else printf("0");
}
printf("\n");
}
else {
for(int i=1;i<=n;i++)
printf("0");
printf("\n");
}
}
}