1005:
若没有边权,则对点权从大到小排序即可。。
考虑边,将边权拆成两半加到它所关联的两个点的点权中即可。
。。因为当两个人分别选择不同的点时,这一权值将互相抵消。
智商是硬伤啊
#include<iostream>
#include<algorithm>
#include<string.h>
#include<stdio.h>
using namespace std;
double w[100001];
int main()
{
//freopen("1005.in","r",stdin);
int n,m,i,a,c,b;
while(~scanf("%d%d",&n,&m))
{
memset(w,0,sizeof(w));
for(i=1;i<=n;i++)scanf("%lf",&w[i]);
for(i=1;i<=m;i++)
{
scanf("%d%d%d",&a,&b,&c);
w[a]+=1.0*c/2;
w[b]+=1.0*c/2;
}
double s;
s=0;
sort(w+1,w+n+1);
for(i=n;i>=1;i-=2)
{
s+=w[i]-w[i-1];
}
printf("%.0lf\n",s);
}
return 0;
}
1006:
数组sum[i]:代表第i个数和其之前的数的和对m取余。
若sum[i]=sum[j],那么i和j之间的数肯定满足是m的倍数,则就可以去掉,问题转化成找最大的(j-i)使得sum[j]=sum[i];
在读入数据的时候对sum[i]=x进行标记,若之前标记过sum[j]=x,那么计算差值(j-i),取最大值。
#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<string.h>
using namespace std;
#define maxn 100005
#define ll __int64
ll vis[maxn*2];
int main()
{
//freopen("data.in","r",stdin);
ll i,n,m;
ll sum;
ll a;
while(scanf("%I64d%I64d",&n,&m)!=EOF)
{
sum=0;
int ans=0;
memset(vis,-1,sizeof(vis));
vis[0]=0;
int maxm=100000;
for(i=1;i<=n;i++)
{
scanf("%I64d",&a);
a=a%m;
sum=sum+a;
sum=sum%m;
if(sum<0)
{
if(vis[sum+maxm]==-1)vis[sum+maxm]=i;
else if(ans<i-vis[sum+maxm])ans=i-vis[sum+maxm];
//continue;
}
if(sum<0)sum=sum+m;
if(vis[sum]==-1)vis[sum]=i;
else
{
if(ans<i-vis[sum])ans=i-vis[sum];
}
}
cout<<ans<<endl;
}
return 0;
}
1007:
对位的进制进行dp。
dp[i][j][k]:运行到第i个数,第j位为k(0或1)的概率。
lc[i][j] :第i个数的第j位为多少(0或者1)
p[i] :第i个数加入运算的概率。
若运算符为^
dp[i][j][0]=dp[i-1][j][0]*(1-p[i]);
dp[i][j][1]=dp[i-1][j][0]*(1-p[i]);//这两条是若此数为加入运算。
dp[i][j][0^lc[i][j]]+=dp[i-1][j][0]*p[i];
dp[i][j][1^lc[i][j]]+=dp[i-1][j][1]*p[i];//这两条是若此数加入了运算
#include<stdio.h>
#include<vector>
#include<string.h>
#include<iostream>
using namespace std;
int lc[301][22];
int fu[301];
double p[301];
double dp[301][301][30];
int n;
int main()
{
int cas=1,i,t,a;
char str[1001];
while(scanf("%d%*c",&n)!=EOF)
{
memset(dp,0,sizeof(dp));
memset(lc,0,sizeof(lc));
for(i=0;i<=20;i++)p[i]=0;
for(i=0;i<=n;i++)
{
scanf("%d",&a);
int cs=1;
while(a)
{
lc[i][cs]=a%2;
a=a/2;
cs++;
}
}
getchar();
gets(str);
for(i=1;i<=n;i++)
{
if(str[i*2-2]=='^')fu[i]=1;
else if(str[i*2-2]=='|')fu[i]=2;
else if(str[i*2-2]=='&')fu[i]=3;
}
p[0]=1;
double cp;
for(t=1;t<=20;t++)
{
if(lc[0][t]==1)dp[0][t][1]=1;
else dp[0][t][0]=1;
}
for(i=1;i<=n;i++)
{
scanf("%lf",&cp);
p[i]=1-cp;
}
for(i=1;i<=n;i++)
{
for(t=1;t<=20;t++)
{
dp[i][t][0]=dp[i-1][t][0]*(1-p[i]);
dp[i][t][1]=dp[i-1][t][1]*(1-p[i]);
if(fu[i]==1)
{
dp[i][t][0^lc[i][t]]+=dp[i-1][t][0]*p[i];
dp[i][t][1^lc[i][t]]+=dp[i-1][t][1]*p[i];
}
else if(fu[i]==2)
{
dp[i][t][0|lc[i][t]]+=dp[i-1][t][0]*p[i];
dp[i][t][1|lc[i][t]]+=dp[i-1][t][1]*p[i];
}
else if(fu[i]==3)
{
dp[i][t][0&lc[i][t]]+=dp[i-1][t][0]*p[i];
dp[i][t][1&lc[i][t]]+=dp[i-1][t][1]*p[i];
}
}
}
double ans;
ans=0.0;
for(t=1;t<=20;t++)
{
ans+=dp[n][t][1]*(1<<(t-1));
}
printf("Case %d:\n%.6lf\n",cas++,ans);
}
return 0;
}
1009:
给你一个数n,问你n能分成多少种数相加。
比如3=1+1+1,3=1+2,3=3
f[3]=3;
参见五边形定理.
#include<iostream>
#include<stdio.h>
using namespace std;
#define mo 1000000007
__int64 f[100001];
int main()
{
int T,i,k,n;
scanf("%d",&T);
f[1]=1;
f[0]=1;
for(i=2;i<=100000;i++)
{
for(k=1;;k++)
{
int t1,t2;
t1=i-k*(3*k+1)/2;
t2=i-k*(3*k-1)/2;
if(k%2==0)
{
if(t1>=0)f[i]-=f[t1];
if(t2>=0)f[i]-=f[t2];
}
else
{
if(t1>=0)f[i]+=f[t1];
if(t2>=0)f[i]+=f[t2];
}
if(t1<=0&&t2<=0)break;
f[i]=f[i]%mo;
if(f[i]<0)f[i]+=mo;
}
}
while(T--)
{
scanf("%d",&n);
printf("%I64d\n",f[n]);
}
return 0;
}
=======持续更新=======