练习赛20150510
练习赛地址http://acm.hrbust.edu.cn/vj/index.php?c=contest-contest&cid=70
a.水。。。
b.暴力打表。。。
c.给四个正方形,求一个能覆盖他们的正方形的面积,其实能覆盖两个最大的正方形就一定能覆盖四个正方形,所以输出两个最大正方形的边长和~\(≧▽≦)/~啦啦啦
d.组合数学,dp[i][j],前表示i个里选j个有多少种情况。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<iostream> #include<stdio.h> #include<string.h> using namespace std; const long long maxa = 104; const long long mod = 1000000007; long long dp[maxa][maxa*maxa]; long long a[maxa*maxa]; long long s[maxa*maxa]; long long c[maxa*maxa][maxa]; int main(){ for(long long i=0;i< maxa*maxa;i++) { for(long long j=0;j<maxa;j++) { if(!j||i==j) c[i][j]=1; else c[i][j]=c[i-1][j-1]+c[i-1][j]; c[i][j] %= mod; } } long long n; long long cas = 1; while(cin>>n){ memset(dp, 0, sizeof(dp)); for(long long i =0; i < n; i++){ cin>>a[i]; if(i == 0) s[i] = a[i]; else s[i] = s[i-1]+a[i]; } for(long long i = 0;i < n; i++){ if(i == 0){ for(long long j = 0; j <= a[i]; j++){ dp[i][j] = 1; } }else{ for(long long j = 0; j <= a[i]; j++){ for(long long k = 0;k <= s[i-1]; k++){ dp[i][j+k] += dp[i-1][k]*(c[j+k][j]); dp[i][j+k] %= mod; } } } } long long ans = 0; for(long long i = 1; i <= s[n-1]; i++){ ans += dp[n-1][i]; ans %= mod; } cout<<"Case "<<cas++<<": "<<ans<<"\n"; } }
e.简单数位dp
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<iostream> #include<string.h> #include<stdio.h> using namespace std; const long long maxa = 11; long long dp[maxa][maxa*2]; char str1[maxa], str2[maxa], str3[maxa]; char str[1111]; int main(){ int cas = 1; //while(scanf("%[^+]%*c%[^=]%*c%[^\n]\n", str1, str2, str3)!=EOF){ //scanf("%*[ \n]"); while (gets(str)) { //scanf("%*[ \n]"); sscanf(str, "%[^+]+%[^=]=%s", str1, str2, str3); long long l1 = strlen(str1); long long l2 = strlen(str2); long long l3 = strlen(str3); memset(dp, 0, sizeof(dp)); //printf("%s\n%s\n%s\n", str1, str2, str3); //printf("%d %d %d\n", l1, l2, l3); if(l1 > l3 || l2 > l3){ printf("Case %d: %d\n", cas++, 0);//printf("//"); continue; } for(long long i = 1;i <= l3; i++){ if(i == 1){ //printf("++%c\n",str1[l1-1]); for(long long i1 = 0; i1 < 10; i1++){ if(str1[l1-1] != '?' && i1 != str1[l1-1]-'0')continue;//printf("**%d\n", i1); for(long long i2 = 0; i2 < 10; i2 ++){ if(str2[l2-1] != '?' && i2 != str2[l2-1]-'0')continue; //printf("*%d %d\n", i1, i2); long long sum = i1 +i2; if(str3[l3-1] != '?' && sum % 10 != str3[l3-1]-'0')continue; dp[i][sum] ++; } } continue; } for(long long k = 0; k < 20; k++){ if(i != 1 && dp[i-1][k] == 0)continue; //printf("%c %c %c\n", str1[l1-i], str2[l2-i], str2[l3-i]); for(long long i1 = 0; i1 < 10; i1++){ if(i1 == 0 && i == l1)continue; if(i > l1 && i1) continue; if(i <= l1 && str1[l1-i] != '?' && i1 != str1[l1-i] - '0')continue; for(long long i2 = 0; i2 < 10; i2++){ if(i > l2 && i2)continue; if(i == l2 && i2 == 0) continue; if(i <= l2 && str2[l2-i] != '?' && i2 != str2[l2-i]-'0')continue; long long sum = i1+i2 + k/10; if(str3[l3-i] != '?' && str3[l3-i]-'0' !=sum % 10)continue; //printf("--%d %d %d %d\n", i1, i2, sum , k); dp[i][sum] += dp[i-1][k]; } } } } long long ans = 0; for(long long i = l3==1 ? 0:1; i < 10 ; i++){ //printf("%d ", dp[1][i]); ans += dp[l3][i]; } printf("Case %d: ", cas++); cout << ans << endl; } } /* 100+?=??? */
f.划分树模板题,但是没带。。。。
g.水题,栈操作