Description:
在一个 n ∗ m n*m n∗m的只包含0,1的矩形中,求有多少个特殊的子矩形,特殊的字矩形满足
它的四条边上都是1,内部的0,1个数差不超过1,大小至少为2*2。
n , m ≤ 300 n,m\le300 n,m≤300
Solution:
Code:
#include
using namespace std;
#define REP(i,f,t) for(int i=(f),i##_end_=(t);i<=i##_end_;++i)
#define ll long long
const int N=302,M=90000;
int n,m;
int A[N][N];
int col[N][N];
int cnt[M*2+5],mark[M*2+5];
int main(){
// freopen("matrix.in","r",stdin);
// freopen("matrix.out","w",stdout);
scanf("%d%d",&n,&m);
REP(i,1,n) REP(j,1,m) scanf("%d",&A[i][j]),col[i][j]=col[i-1][j]+A[i][j];
int ans=0;
REP(i,1,n) REP(j,i+1,n){
int tot=0,sum=0,len=j-i+1;
REP(k,1,m){
int res=(len-2)-2*(col[j-1][k]-col[i][k]);
if(len==col[j][k]-col[i-1][k]){
ans+=cnt[sum+M]+cnt[sum+M-1]+cnt[sum+M+1];
cnt[sum+M+res]++;
mark[++tot]=sum+M+res;
}
if(!A[j][k] || !A[i][k]) {
REP(l,1,tot)cnt[mark[l]]=0;
tot=0;
}
sum+=res;
}
REP(l,1,tot) cnt[mark[l]]=0;
}
printf("%d\n",ans);
return 0;
}
Description:
一个有 n n n个格子的带子,每个格子可以涂成黑色或白色,而对于一条涂好的带子,对于每一个格子,它的花费为与之不同颜色的最近的距离和当前格子的颜色权值的乘积,即 c o s t i = d i s i ∗ v a l [ i ] [ c o l i ] , c o l i cost_i=dis_i*val[i][col_i],col_i costi=disi∗val[i][coli],coli为0或1,表示黑白。
求这带子的最小花费。
n ≤ 4000 , v a l [ i ] [ 0 / 1 ] ≤ 1 0 5 n\le4000,val[i][0/1]\le10^5 n≤4000,val[i][0/1]≤105
Solution:
Code:
#include
using namespace std;
#define REP(i,f,t) for(int i=(f),i##_end_=(t);i<=i##_end_;++i)
#define SREP(i,f,t) for(int i=(f),i##_end_=(t);i=i##_end_;--i)
#define ll long long
templateinline bool chkmin(T &x,T y){return x>y?x=y,1:0;}
const int N=4010;
int n;
struct node{
int a,b;
}A[N];
struct p20{
void solve(){
SREP(i,0,n) scanf("%d%d",&A[i].a,&A[i].b);
ll ans=0x3f3f3f3f;
int t[11];
SREP(s,1,(1<=0 && !t[i-k]) {res+=k*A[i].b;break;}
if(i+k=0 && t[i-k]) {res+=k*A[i].a;break;}
if(i+k>1;
if(j+1==1 && i==n) res=1e17;
else if(j+1==1) res=R[!k][l]-R[!k][r+1]-(sum[!k][r]-sum[!k][l-1])*(n-r);
else if(r==n) res=L[!k][r]-L[!k][l-1]-(sum[!k][r]-sum[!k][l-1])*(l-1);
else res=L[!k][mid]-L[!k][l-1]-(sum[!k][mid]-sum[!k][l-1])*(l-1)+R[!k][mid+1]-R[!k][r+1]-(sum[!k][r]-sum[!k][mid])*(n-r);
if(~dp[k][i]) chkmin(dp[k][i],dp[!k][j]+res);
else dp[k][i]=dp[!k][j]+res;
}
printf("%lld\n",min(dp[0][n],dp[1][n]));
}
}p2;
int main(){
// freopen("build.in","r",stdin);
// freopen("build.out","w",stdout);
scanf("%d",&n);
if(n<=10) p1.solve();
else p2.solve();
return 0;
}
Description:
有一棵 n n n个节点的树,每个节点有一个 v a l i val_i vali,求出所有 v a l val val互质的节点的距离和。
n , v a l i ≤ 1 0 5 n,val_i\le10^5 n,vali≤105
Solution:
Code:
#include
using namespace std;
#define REP(i,f,t) for(int i=(f),i##_end_=(t);i<=i##_end_;++i)
#define SREP(i,f,t) for(int i=(f),i##_end_=(t);i=i##_end_;--i)
#define ll long long
templateinline bool chkmin(T &x,T y){return x>y?x=y,1:0;}
templateinline bool chkmax(T &x,T y){return xinline void Rd(T &x){
x=0;char c;
while((c=getchar())<48);
do x=(x<<1)+(x<<3)+(c^48);
while((c=getchar())>47);
}
const int N=1e5+2;
int n;
int val[N];
int head[N],qwq;
struct edge{
int to,nxt;
}E[N<<1];
void addedge(int x,int y){E[qwq]=(edge){y,head[x]};head[x]=qwq++;}
int Mx;
int fa[N],dep[N],sz[N],son[N],top[N];
struct p30{
int gcd(int a,int b){return !b?a:gcd(b,a%b);}
void dfs1(int x,int f){
fa[x]=f;
dep[x]=dep[f]+1;
sz[x]=1;
for(int i=head[x];~i;i=E[i].nxt){
int y=E[i].to;
if(y==f)continue;
dfs1(y,x);
sz[x]+=sz[y];
if(sz[son[x]]prime[505];
void Init(){
REP(i,2,500){
int x=i;
for(int j=2;j<=x;++j){
if(x%j==0){
prime[i].push_back(j);
while(x%j==0)x/=j;
}
}
}
}
void calc(int x){
memset(cnt1,0,sizeof(cnt1));
memset(cnt2,0,sizeof(cnt2));
REP(i,1,Mx) for(int j=1;j*j<=i;++j) {
if(i%j)continue;
cnt1[j]+=dp[x][i];
cnt2[j]+=c[x][i];
if(i/j!=j) {
cnt1[i/j]+=dp[x][i];
cnt2[i/j]+=c[x][i];
}
}
}
void dfs(int x,int f){
for(int i=head[x];~i;i=E[i].nxt){
int y=E[i].to;
if(y==f)continue;
dfs(y,x);
ll sum1=0,sum2=0;
REP(j,1,Mx) sum1+=dp[x][j],sum2+=c[x][j];
calc(x);
REP(j,1,Mx){
if(!c[y][j])continue;
int l=(1<<(prime[j].size()));
ll tot1=0,tot2=0;
SREP(k,1,l){
int tmp=1,t1=0;
SREP(p,0,prime[j].size()) if(k&(1<T[N];
int mu[N];
ll calc(int k){
int len=0,top=0;
for(int i=k;i
总结: