2019 icpc 南昌
7 / 50 A 9102 !!!
99 / 175 B A Funny Bipartite Graph !!!
爆搜跑的飞快,网络流原地爆炸
就是对右边点每个点选边进行爆搜,复杂度3^n,为什么不对左边爆搜呢,因为不好确定左边到底选多少条边,枚举又得乘个8,但是右边最优策略就是只选一条边,多选没有意义
代码:
#include<bits/stdc++.h>
using namespace std;
const int maxn=25;
int n;
char a1[maxn][maxn],g1[maxn][maxn],m[maxn],flag[maxn];
vector<int>e[maxn];
vector<int>edge[maxn];
int ans=1e9;
int d[maxn],vis[maxn];
int js(int x,int n)
{
if(n==0) return 0;
int ans=1;
for(int i=1;i<=n;i++) ans*=m[x];
return ans;
}
void dfs(int u,int s)
{
if(s>=ans) return;
if(u==n+1)
{
ans=s;
return;
}
for(int v:e[u])
{
if(vis[v]==0)
{
d[v]++;
for(int i:edge[v]) vis[i]++;
dfs(u+1,s+js(v,d[v])-js(v,d[v]-1));
for(int i:edge[v]) vis[i]--;
d[v]--;
}
}
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
for(int i=0;i<=n+1;i++) e[i].clear(),edge[i].clear();
memset(d,0,sizeof(d));ans=1e9;
memset(vis,0,sizeof(vis));
for(int i=1;i<=n;i++)
{
scanf("%s",a1[i]+1);
for(int j=1;j<=n;j++)
{
if(a1[i][j]=='1')
{
//edge[i].push_back(j);
e[j].push_back(i);
}
}
}
for(int i=1;i<=n;i++)
{
scanf("%s",g1[i]+1);
for(int j=1;j<=n;j++)
{
if(g1[i][j]=='1')
{
edge[i].push_back(j);
}
}
}
for(int i=1;i<=n;i++) scanf("%d",&m[i]);
dfs(1,0);
if(ans==1e9) printf("-1\n");
else printf("%d\n",ans);
}
}
26 / 35 C And and Pair ---
89 / 293 D Bitwise Tree +++
24 / 113 E Bob's Problem ---
41 / 270 F Dynamic Suffix Array ???
17 / 58 G Eating Plan ---
H Powers of Two ???
1 / 17 I Resistance ???
2 / 5 J Summon ???
polya定理,如果没有限制的话,答案就是\(\frac{1}{n}\)\(\sum_{k=1}^{n}\)\(m^{gcd(n,k)}\),但是有限制的话就要考虑限制了,无限制的情况,本质是确定了前gcd(n,k)个数后,后面的数也都确定了,所以我们枚举gcd(n,k),然后我们建立矩阵,第i行第j列等于1代表可以由i到j转化,i位的后俩位和j位的第二三列是相同的(四进制情况下),矩阵的gcd(n,k)次幂后,每一位值的和就是gcd(n,k)对应的答案,详情看代码
#include<stdio.h>
#include<string.h>
const int N=64;
#define mod 998244353
#define ll long long
struct mt{
int a[N][N];
mt (){memset(a, 0, sizeof a);}
void E(){for(int i = 0; i < N; ++i) a[i][i] = 1;}
void F(){for(int i = 0; i < N; ++i) for(int j = 0; j < N; ++j) a[i][j] = 1;}
mt operator * (mt x){
mt ans;
for(int i = 0; i < N; ++i){
for(int k = 0; k < N; ++k){
if(!a[i][k]) continue;
for(int j = 0; j < N; ++j){
ans.a[i][j]+=(ll)a[i][k]*x.a[k][j]%mod;
ans.a[i][j] %= mod;
}
}
}return ans;
}
}base, pbase[20];
#define maxn 100100
int phi[maxn],vis1[maxn],vis2[maxn],prime[maxn];
void inite(){
phi[1]=1;
int cnt=0;
for(int i=2;i<=100000;i++){
if(vis1[i]==0){
phi[i]=i-1;
prime[++cnt]=i;
}
for(int j=1;j<=cnt&&i*prime[j]<=100000;j++){
vis1[i*prime[j]]=1;
if(i%prime[j]==0){
phi[i*prime[j]]=phi[i]*prime[j];
break;
}
else{
phi[i*prime[j]]=phi[i]*phi[prime[j]];
}
}
}
for(int i=0;i<64;i++){
for(int j=0;j<4;j++){
int now=(i*4+j)%64;
base.a[i][now]=1;
}
}
}
mt quickpow(ll cnt){
mt ans;
ans.E();
for(int i=0;;i++){
if(cnt%2==1){
ans=ans*pbase[i];
}
cnt=cnt/2;
if(cnt==0)break;
}
return ans;
}
int get(int a,int b,int c,int d){
return a*64+b*16+c*4+d;
}
ll quickpow(ll a,ll b){
ll ans=1;
while(b!=0){
if(b%2==1)ans=(ans*a)%mod;
a=a*a%mod;
b=b/2;
}
return ans;
}
int main(){
inite();
int n,m;
scanf("%d %d",&n,&m);
for(int i=1;i<=m;i++){
int now=0;
for(int j=1;j<=4;j++){
int x;
scanf("%d",&x);
now=now*4+x;
}
vis2[now]=1;
base.a[now/4][now%64]=0;
}
pbase[0]=base;
for(int i=1;i<20;i++)pbase[i]=pbase[i-1]*pbase[i-1];
ll ans=0;
for(int i=0;i<4;i++){
int now=0;
for(int cnt=1;cnt<=4;cnt++){
now=now*4+i;
}
if(vis2[now]==0)ans++;
}
ans=(ans*phi[n])%mod;
if(n%2==0){
ll temp=0;
for(int i=0;i<4;i++){
for(int j=0;j<4;j++){
int now1=get(i,j,i,j);
int now2=get(j,i,j,i);
if(vis2[now1]==0&&vis2[now2]==0)temp++;
}
}
ans=(ans+temp*phi[n/2])%mod;
}
for(int i=3;i<=n;i++){
if(n%i!=0)continue;
mt res;
res.E();
res=res*quickpow(i);
ll temp=0;
for(int j=0;j<64;j++)temp=(temp+res.a[j][j])%mod;
temp=temp*phi[n/i]%mod;
ans=(ans+temp)%mod;
}
ans=(ans*quickpow(n,mod-2))%mod;
printf("%lld\n",ans);
}


浙公网安备 33010602011771号