送分向水题,直接模拟即可。
1 #include<iostream> 2 #include<cstdio> 3 #define N 1505 4 using namespace std; 5 int n,m,k,a[N],now,ans,hve[N]; 6 int main() 7 { 8 cin>>n>>m>>k; 9 for(int i=1;i<=k;i++)cin>>a[i],hve[a[i]]=1; 10 while(now<n) 11 { 12 ans++; 13 now+=m; 14 if(hve[now])m++; 15 } 16 cout<<ans<<endl; 17 return 0; 18 }
枚举$x,y$,根据$xor$的性质算出z。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<cmath> 5 #define N 2005 6 using namespace std; 7 int n,m,a[N],b[N],c[N],ans; 8 int main() 9 { 10 //freopen("1.in","r",stdin); 11 //freopen("1.out","w",stdout); 12 cin>>n>>m; 13 for(int i=1;i<=n;i++)cin>>a[i]>>b[i]>>c[i]; 14 for(int x=1;x<=m;x++) 15 { 16 for(int y=1;y<=m;y++) 17 { 18 int z=((abs(a[1]-x)^abs(b[1]-y)^9)),f=0; 19 //a^b=c 20 //abs(a[1]-x)^abs(b[1]-y)^z=9 21 int zz=c[1]-z; 22 if(zz>m||zz<=0)f=1; 23 for(int i=1;i<=n;i++) 24 { 25 if((abs(a[i]-x)^abs(b[i]-y)^abs(c[i]-zz))!=9)f=1; 26 } 27 if(!f)ans++; 28 int ff=0,_zz=c[1]+z; 29 if(_zz>m||_zz<=0||zz==_zz)ff=1; 30 for(int i=1;i<=n;i++) 31 { 32 if((abs(a[i]-x)^abs(b[i]-y)^abs(c[i]-_zz))!=9)ff=1; 33 } 34 if(!ff)ans++; 35 } 36 } 37 cout<<ans<<endl; 38 return 0; 39 }
考试时写了50分做法,枚举每一个边选或不选,然后判断是否是凸多边形,判断一些边能否组成凸多边形很简单,看一下是否出最大值外的权值和是否大于最大值即可。
50分代码:
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #define int long long 5 #define N 5005 6 #define p (long long)(1e9+7) 7 using namespace std; 8 int T,n,ans,a[N]; 9 int ksm(int a,int b) 10 { 11 int r=1; 12 while(b) 13 { 14 if(b&1)r*=a,r%=p; 15 a*=a;a%=p; 16 b>>=1; 17 } 18 return r; 19 } 20 void dfs(int t,int sum,int maxn,int tot) 21 { 22 if(t==n+1) 23 { 24 if(maxn<sum-maxn) 25 { 26 ans+=tot; 27 ans%=p; 28 } 29 return; 30 } 31 a[t]=0; 32 dfs(t+1,sum,maxn,tot); 33 a[t]=1; 34 dfs(t+1,sum+t,t,tot+1); 35 } 36 signed main() 37 { 38 cin>>T; 39 while(T--) 40 { 41 cin>>n;ans=0; 42 dfs(1,0,0,0); 43 cout<<(ans*ksm((1<<n),p-2))%p<<endl; 44 } 45 }
满分做法是$DP$。
设$f_i$为选出边长和为$i$的不合法方案数
设$w_i$为选出边长和为$i$的不合法权值和
对于$f$的转移,直接背包即可。
对于$w$的转移: 我们考虑加入一条长度$i$的边加入边集,那么如果是从$w[j-i]$转移到 $w[j]$, 那么就会在$w[j-i]$的所有状态的边集中加入一条长度为$i$的边然后考虑的不同的边集个数是$f[j-i]$那么在每一个边集中加入一条边的权值和, 就等价于在原本的权值和的基础上加上等同于边集的个数。
然后从小到大枚举并且累加答案即可。
100分代码:
#include<iostream> #include<cstdio> #include<cstring> #define N 5005 #define int long long #define p (long long)(1e9+7) using namespace std; int read() { int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+(ch^48);ch=getchar();} return x*f; } int ksm(int a,int b) { int r=1; while(b) { if(b&1)r*=a,r%=p; a*=a;a%=p; b>>=1; } return r; } int T,n,f[N],w[N],s[N]; void init(int n) { f[0]=1; for(int i=1;i<=n;i++) { s[i]=s[i-1]; for(int j=0;j<=i;j++)s[i]=(s[i]+f[j]+w[j])%p; for(int j=n;j>=i;j--)f[j]=(f[j]+f[j-i])%p,w[j]=(w[j]+f[j-i]+w[j-i])%p; } } signed main() { T=read(); init(N-5); while(T--) { n=read(); int xx=ksm(ksm(2,n),p-2)%p,xxx=1ll*n*ksm(2,n-1)%p; cout<<(xx*(((xxx-s[n])%p)+p)%p)%p<<endl; } }
等我看懂题解......