2013腾讯编程马拉松初赛第1场(3月21)(HDU 4505 HDU4506 HDU4507 HDU4508 HDU4509)

A题 (hdu 4505)

题目链接:    http://acm.hdu.edu.cn/showproblem.php?pid=4505

解题思路:    水题没啥好说的,一般10分钟就能出来这道题。。。。1a

代码:

[cpp]  view plain copy
  1. #include <iostream>  
  2. #include <algorithm>  
  3. using namespace std;  
  4. const int maxn = 20;  
  5. int main()  
  6. {  
  7.     int t, n, a[maxn];  
  8.     scanf("%d", &t);  
  9.     while (t--)  
  10.     {  
  11.         scanf("%d", &n);  
  12.         int i;  
  13.         for (i=0; i<n; i++)  
  14.         {  
  15.             scanf("%d", &a[i]);  
  16.         }  
  17.         sort(a, a+n);  
  18.         int ans = 0;  
  19.         int now = 0;  
  20.         for (i=0; i<n; i++, ans++)  
  21.         {  
  22.             if (a[i]<=now)continue;  
  23.             ans += 6 * (a[i] - now);  
  24.             ans += 5;  
  25.             now = a[i];  
  26.         }  
  27.         ans += now * 4;  
  28.         printf("%d\n", ans);  
  29.     }  
  30.     return 0;  
  31. }  

B题 (hdu 4506)

题目链接:    http://acm.hdu.edu.cn/showproblem.php?pid=4506

解题思路:   这道题真晕。。我没做,最后发现其实我应该做这道题,不用啥技巧。。用了个快速幂。。。1a。。。

快速幂请参见:http://blog.csdn.net/liuqiyao_01/article/details/8478402

代码:

#include <iostream>
using namespace std;

const __int64 tmp = 1000000007;
const int maxn = 10005;
__int64 n, t, k, a[maxn];

__int64 qpow(int a, int b)
{
	__int64 c, d;
	c = 1; d = a;
	while (b > 0)
	{
		if (b & 1)
		c *= d;
		c %= tmp;
		b = b >> 1;
		d = (d * d) % tmp;
	}
	return c % tmp;
}

int main()
{
	int T;
	scanf("%d", &T);
	while (T--)
	{
		scanf("%I64d %I64d %I64d", &n, &t, &k);
		int i;
		__int64 multi = qpow(k,t);
		for (i=0; i<n; i++)
		{
			scanf("%I64d", &a[i]);
			a[i] = a[i] * multi % tmp;
		}
		t %= n;
		printf("%d", a[(n+0-t)%n]);
		for (i=1; i<n; i++)
		{
			printf(" %d", a[(n+i-t)%n]);
		}
		puts("");
	}
	return 0;
}



C题 (hdu 4507)

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=4507

解题思路:木有,据说是数位DP。。。

代码:无解啊有木有。。。据说这也只是regional 的初期题。。。。。

网上大牛代码~~ACM一群   [退队狗]cherudim   提供!

#include <cstdio>
#include <algorithm>
#include <cstdlib>
#include <sstream>
#include <iostream>
#include <string>
#include <cstring>
#define sz(a) ((int)(a).size())
#define Rep(i,j,k) for (int i=(j); i<=(k); i++)
using namespace std;
typedef long long LL;

const int MOD=(int)1e9+7;

struct TT{
	int sq, sum, num;
} f[22][2][7][7][2];

TT ff(TT a, int b){
	a.sq=(a.sq*100LL+20LL*a.sum*b+b*b*(LL)a.num)%MOD;
	a.sum=(a.sum*10LL+(LL)a.num*b)%MOD;
	return a;
}

void update(int &x, int y){
	x+=y;
	if (x>=MOD)
		x-=MOD;
}

void update(TT & a, TT b){
	update(a.sq,b.sq);
	update(a.sum,b.sum);
	update(a.num,b.num);
}

int doit(LL n){
	if (n==0) return 0;

	memset(f,0,sizeof f);

	f[0][0][0][0][0].num=1;

	stringstream sss;sss<<n;string ss;sss>>ss;
	int m=sz(ss);

	Rep(i,0,m-1)
		Rep(con7,0,1)
			Rep(dig7,0,6)
				Rep(n7,0,6)
					Rep(same,0,1)
						Rep(p,0,9){
							if (same==0 && p>ss[i]-'0')
								continue;
							int Ncon7=con7 || (p==7),
								Ndig7=(dig7+p)%7,
								Nn7=(n7*10+p)%7;
							int Nsame=same;
							if (same==0 && p<ss[i]-'0')
								Nsame=1;
							update(f[i+1][Ncon7][Ndig7][Nn7][Nsame],ff(f[i][con7][dig7][n7][same],p));
						}

	int ans=0;

	Rep(con7,0,1)
		Rep(dig7,0,6)
			Rep(n7,0,6)
				Rep(same,0,1)
					if (!con7 && dig7 && n7)
						update(ans, f[m][con7][dig7][n7][same].sq);

	return ans;
}

int main(){

	int T;
	cin>>T;
	while(T--){
		LL L,R;
		cin>>L>>R;
		cout<<(doit(R)-doit(L-1)+MOD)%MOD<<endl;
	}

    return 0;
}

这里还有另一个大牛的(转自:http://blog.csdn.net/acm_cxlove/article/details/8707084

其实还是比较裸的数位DP。
给出的三种定义,都可以用位DP解决。而且是比较基础的。
至于平方和,大概是这样的。
我们假设dfs进下一层的数字是x,那么当前长度是len的话,最高位添加的数字是i
那么我们令f=i*10^(len-1),那么f+x便是当前的数。
如果是平方的话,然后将其展开f^2+x^2+2*f+x。
其实sigma(x^2)大概就是整个题目要求维护的结果,sigma(f^2)也是可以求的,那么还需要sigma(2*f*x),也就是sigma(x)。
可以看出我们需要维护三个东西,与7有关的数有多少个,sigma(与7有关的数),sigma(与7有关的数的平方)。
剩下的都没什么问题了,求整个的平方和,然后减去与7有关的数的平方和,就是结果。
大概注意下各个地方不要溢出就行了。

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<cmath>
#include<iostream>
#define LL long long
#define MOD 1000000007
#define mp(a,b) make_pair(a,b)
using namespace std;
//长度,是否有7,数字和%7,数字%7
LL s1[20][2][7][7],s2[20][2][7][7],cnt[20][2][7][7];
int bit[20],len;
LL fac[20]={1};
pair<pair<int,int>,int> dfs(int len,int a,int b,int c,int limit){
    if(cnt[len][a][b][c]!=-1&&!limit) return mp(mp(cnt[len][a][b][c],s1[len][a][b][c]),s2[len][a][b][c]);
    if(!len){
        if(!a&&b&&c) cnt[len][a][b][c]=0LL;
        else cnt[len][a][b][c]=1LL;
        s1[len][a][b][c]=s2[len][a][b][c]=0LL;
        return mp(mp(cnt[len][a][b][c],s1[len][a][b][c]),s2[len][a][b][c]);
    }
    int up=limit?bit[len]:9;
    LL tcnt=0LL,ts1=0LL,ts2=0LL;
    for(int i=0;i<=up;i++){
        int nl=len-1,na=(a||i==7),nb=(b+i)%7,nc=(c*10+i)%7;
        LL f=(fac[len-1]*i)%MOD;
        pair<pair<int,int>,int> pre=dfs(nl,na,nb,nc,limit&&(i==up));
        ts1=(ts1+pre.first.second+pre.first.first*f)%MOD;
        ts2=(ts2+pre.second+(f*f%MOD)*pre.first.first+2*f*pre.first.second)%MOD;
        tcnt=(tcnt+pre.first.first)%MOD;
    }  
    if(!limit){
        cnt[len][a][b][c]=tcnt;
        s1[len][a][b][c]=ts1;
        s2[len][a][b][c]=ts2;
    }
    return mp(mp(tcnt,ts1),ts2);
}
LL sum(LL n){
    LL a=n,b=n+1,c=2*n+1;
    int x=3,y=2;
    if(a%x==0) a/=x,x=1;if(a%y==0) a/=y,y=1;  
    if(b%x==0) b/=x,x=1;if(b%y==0) b/=y,y=1;
    if(c%x==0) c/=x,x=1;if(c%y==0) c/=y,y=1;
    a%=MOD;b%=MOD;c%=MOD;
    return (a*b%MOD)*c%MOD;
}
LL slove(LL n){
    len=0;
    LL m=n;
    while(n){
        bit[++len]=n%10;
        n/=10;
    }
    return (sum(m)-dfs(len,0,0,0,1).second)%MOD;
}
int main(){
    for(int i=1;i<20;i++)
        fac[i]=(fac[i-1]*10)%MOD;
    int t;
    LL l,r;
    memset(cnt,-1,sizeof(cnt));
    scanf("%d",&t);
    while(t--){
        scanf("%I64d%I64d",&l,&r);
        //cout<<slove(r)<<" "<<slove(l-1)<<endl;
        printf("%I64d\n",((slove(r)-slove(l-1))%MOD+MOD)%MOD);
    }
    return 0;
}



D题 (hdu 4508)

题目链接:    http://acm.hdu.edu.cn/showproblem.php?pid=4508

解题思路:    0-1背包的模版题,不一定要把背包装满,调试的时候数组开小RE3次、。。。。。太粗心了。。。。

代码:

[cpp]  view plain copy
  1. #include <iostream>  
  2. using namespace std;  
  3.   
  4. #define max(a,b)    ((a)>(b)?(a):(b))  
  5. const int maxn = 105;  
  6.   
  7. int main()  
  8. {  
  9.     int n, m;  
  10.     int a[maxn], b[maxn], dp[100005];  
  11.     while (scanf("%d", &n) != EOF)  
  12.     {  
  13.         int i, j;  
  14.         for (i=1; i<=n; i++)  
  15.             scanf("%d %d", &a[i], &b[i]);  
  16.         scanf("%d", &m);  
  17.         memset(dp, 0, sizeof(dp));  
  18.         for (i=1; i<=n; i++)  
  19.         {  
  20.             for (j=0; j<=m; j++)  
  21.             {  
  22.                 if (b[i] > j) continue;  
  23.                 dp[j] = max(dp[j], dp[j-b[i]] + a[i]);  
  24.             }  
  25.         }  
  26.         printf("%d\n", dp[m]);  
  27.     }  
  28.     return 0;  
  29. }  


E题(hdu 4509)

题目链接:    http://acm.hdu.edu.cn/showproblem.php?pid=4509

解题思路:    一开始xindoo和我说穷举。。我一看输入量,觉得穷举肯定没戏,但是想不出别的方法,于是穷举,思路乱七八糟的wa了3次。。郁闷啊。。直到他们出了这道题,我就没做。。22号看网上大牛用memset,很好用。。。第一次学。。以后一定能用上。

代码:

[cpp]  view plain copy
  1. #include <iostream>  
  2. #include <algorithm>  
  3. using namespace std;  
  4.   
  5. const int maxn = 500005;  
  6. int n;  
  7.   
  8. int main()  
  9. {  
  10.     int flag[1440];  
  11.     while (scanf("%d", &n) != EOF)  
  12.     {  
  13.         int sh, sm, eh, em;  
  14.         memset(flag, -1, sizeof(flag));  
  15.   
  16.         int i;  
  17.         int ans = 0;  
  18.         for (i=0; i<n; i++)  
  19.         {  
  20.             scanf("%d:%d %d:%d", &sh, &sm, &eh, &em);  
  21.             int s = sh * 60 + sm;  
  22.             int e = eh * 60 + em;  
  23.             memset(flag + s, 0, (e-s)*sizeof(flag[0]));  
  24.         }  
  25.         for (i=0; i<1440; i++)  
  26.             if (flag[i])  
  27.                 ans++;  
  28.         printf("%d\n", ans);  
  29.     }   
  30.     return 0;  
  31. }  
评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值