B题Bigger is Better :
题意:
用有限火柴棍拼数字,能整除m的最大数字。
tip:
f[I][j]用了I根火柴%m为j的最大数字是多少。
最多50位,用高精度,缩位
#include <cstdio>
#include <iostream>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
int ca;
const int MOD = 100000000;
int n,m;
struct BigInt{
int len,a[8];
void clear(){
len = 0;//a[1] = 0;//memset(a,0,sizeof(a));
for(int i = 0 ; i < 8 ; i++) a[i] = 0;
}
void out(){
for(int i = len ; i >= 1 ; i--){
if(i != len) printf("%08d",a[i]);
else printf("%d",a[i]);
}
if(len == 0) printf("0");
printf("\n");
}
}dp[120][3000];
BigInt Plus(BigInt A,BigInt B){
if(A.len == 1 &&A.a[1] == 0) return B;
BigInt C=A;C.len = max(C.len,B.len)+1;
for(int i = 1; i <= B.len ;i++) C.a[i] += B.a[i];
for(int i = 1; i < C.len ; i++) C.a[i+1] += C.a[i]/MOD,C.a[i]%=MOD;
while(C.len > 0 && C.a[C.len] == 0) C.len--;
return C;
}
BigInt Mul(BigInt A){
if(A.len == 1 && A.a[1] == 0) return A;
BigInt C;C.clear();
if(A.len == 0) return C;
C.len = A.len+1;
for(int i = 1; i <= A.len ;i++){
C.a[i] += A.a[i] * 10;
}
for(int i = 1; i < C.len ; i++){
C.a[i+1] += C.a[i]/MOD;C.a[i] %= MOD;
}
while(C.len > 0 && C.a[C.len] == 0) C.len--;
return C;
}
BigInt IS(int tnum){
int num = tnum;
BigInt AA;AA.len = 1;
AA.a[1] = tnum;
return AA;
}
int compare(BigInt A,BigInt B){
if(A.len > B.len) return 1;
if(A.len < B.len) return -1;
for(int i = A.len ; i >= 1 ; i--){
if(A.a[i] > B.a[i]) return 1;
if(A.a[i] < B.a[i]) return -1;
}
return 0;
}
void sov(){
for(int i = 0 ;i <= n ; i++){
for(int j = 0 ; j < m ; j++){
if(dp[i][j].len == 0) continue;
BigInt tmp,t;
tmp = Mul(dp[i][j]);
if(compare(dp[i+6][(j*10)%m],tmp ) == -1)
dp[i+6][(j*10)%m] = tmp;
t = Plus(tmp,IS(1));
if(compare(dp[i+2][(j*10+1)%m],t) == -1)
dp[i+2][(j*10+1)%m] = t;
t = Plus(tmp,IS(2));
if(compare(dp[i+5][(j*10+2)%m],t) == -1)
dp[i+5][(j*10+2)%m] = t;
t = Plus(tmp,IS(3));
if(compare(dp[i+5][(j*10+3)%m],t)==-1)
dp[i+5][(j*10+3)%m] = t;
t = Plus(tmp,IS(4));
if(compare(dp[i+4][(j*10+4)%m],t)==-1)
dp[i+4][(j*10+4)%m] = t;
t = Plus(tmp,IS(5));
if(compare(dp[i+5][(j*10+5)%m],t)==-1)
dp[i+5][(j*10+5)%m] = t;
t = Plus(tmp,IS(6));
if(compare(dp[i+6][(j*10+6)%m],t)==-1)
dp[i+6][(j*10+6)%m] = t;
t = Plus(tmp,IS(7));
if(compare(dp[i+3][(j*10+7)%m],t)==-1)
dp[i+3][(j*10+7)%m] = t;
t = Plus(tmp,IS(8));
if(compare(dp[i+7][(j*10+8)%m],t) == -1)
dp[i+7][(j*10+8)%m] = t;
t = Plus(tmp,IS(9));
if(compare(dp[i+6][(j*10+9)%m],t)==-1)
dp[i+6][(j*10+9)%m] = t;
}
}
BigInt ans;ans.len = 1;ans.a[1]=0;
int cnt = 0;
for(int i = 0 ; i <= n ; i++){
if(dp[i][0].len == 0 ) {
cnt++;continue;
}
if(compare(ans,dp[i][0]) == -1)
ans = dp[i][0];
}
printf("Case %d: ",++ca);
if(cnt == n && n < 6 ) printf("-1\n");
else ans.out();
}
int main(){
// freopen("out.txt","w",stdout);
while(~scanf("%d",&n)&&n){
scanf("%d",&m);
for(int i = 0 ; i <= n+10 ; i++)
`
or(int j = 0 ; j <= m ; j++) dp[i][j].clear();
dp[0][0].a[1] = 0;dp[0][0].len = 1;
sov();
}
}
D题Digit Puzzle :
题意:
字谜:×× * ×× = ××××
改变给定字谜(不能改位数),但是×和数字可以随便改,使得改变之后的字谜答案是唯一的,问最少改变量时字典序最小的,*比0小
tip:
先一次预处理出来所有答案唯一的字谜,最多99*99个,每个都映射一下,最后只映射了一次的就是答案唯一的,对于每个问题,还是99*99枚举所有的,然后留下改变最少个字典序最小的,每一位都比较一下
#include <cstdio>
#include <iostream>
#include <cstring>
#include <unordered_map>
using namespace std;
unordered_map<unsigned int ,int >mp;
const int N = 10;
const unsigned int hash_star = 10;
char s[N],a[N],b[N],ts[N],ta[N],tb[N],_ans[N];
int lens,lena,lenb,MIN,MINt;
int _a[N],aim[N],ca;
void init(){
for(int i = 1; i <= 99 ; i++){
for(int j = 1; j <= 99 ; j++){
int ans = i*j,k = 0,tmp = 1,jj = j,ii = i,pre =0;
//if(i == 7&& j == 12)cout <<"i = "<<i <<" j = "<<j<<" ans = "<<ans<<endl;
while(ans){
_a[++k] = ans%10;
ans /= 10;
tmp <<= 1;
}
pre = k;
while(jj){
_a[++k] = jj %10;
jj /= 10;
tmp <<= 1;
}
pre = pre*10+k;
while(ii){
_a[++k] = ii % 10;
ii /= 10;
tmp <<= 1;
}
pre = pre*10+k;
//if(tmp > 512) cout <<tmp<<endl;
for(int p = tmp-1 ; p >= 0; p--){
int tt = p,cnt = k+1;
long long _hash = pre;
while(--cnt){
if(tt & 1){
//if(i == 11&&j == 11&&p == 80)cout <<"a[ "<<cnt <<" ] = "<<_a[cnt]<<endl;
_hash =_hash*11 + _a[cnt];
}
else _hash = _hash*11+hash_star;
tt >>= 1;
}
//if(i == 1&&j==10) cout <<"p = "<<p<<" _ hash = "<<_hash<<endl;
// if(_hash == 966196) cout << "i = "<<i<<" j = "<<j<<" p = "<<p <<endl;
int kk = mp[_hash];
if(kk != -1 && kk)
mp[_hash] = -1;
else if(kk == 0) mp[_hash] = 1;
}
}
}
//cout<<"as = "<<mp[966196]<<endl;
}
void check(){
for(int i = (lens == 1?1:10); i <= (lens == 1?9:99) ; i++){
for(int j = (lena == 1?1:10); j <= (lena == 1?9:99) ; j++){
int ans = i*j,k = 0,tmp = 1,jj = j,ii = i,pre;
while(ans){
_a[++k] = ans%10;
ans /= 10;
tmp <<= 1;
}
pre = k;
if(k != lenb) continue;
while(jj){
_a[++k] = jj %10;
jj /= 10;
tmp <<= 1;
}
pre = pre*10+k;
while(ii){
_a[++k] = ii % 10;
ii /= 10;
tmp <<= 1;
}
pre = pre*10+k;
for(int p = 0 ; p <= tmp-1; p++){
int tt = p,cnt = k+1,ch = 0,cmp = 0;
long long _hash = pre;
while(--cnt){
if(tt & 1){
cmp = cmp*10+_a[cnt]+1;
if(aim[cnt] != _a[cnt]) ch++;
_hash =_hash*11 + _a[cnt];
_ans[cnt] = _a[cnt]+'0';
}
else {
cmp *= 10;
if(aim[cnt] != -1) ch++;
_hash = _hash*11+hash_star;
_ans[cnt] = '*';
}
if(ch > MIN)break;
tt >>= 1;
}
if(mp[_hash] == 1 && (ch < MIN || (ch == MIN&&cmp < MINt) )){
//cout <<"i = "<<i<<"j == "<<j<<" ch = "<<ch <<endl;
//for(int ll = k ; ll >= 1 ; ll--) cout <<_ans[ll];
// cout <<endl;
MIN = ch;MINt = cmp;int pp = 0;
tb[lenb] = '\0';ta[lena] = '\0';ts[lens] = '\0';
for(int ll = lenb-1 ; ll >=0 ; ll--)
tb[ll] = _ans[++pp];
for(int ll = lena-1 ; ll >=0 ; ll--)
ta[ll] = _ans[++pp];
for(int ll = lens-1 ; ll >=0 ; ll--)
ts[ll] = _ans[++pp];
}
}
}
}
}
int main(){
init();
while(~scanf("%s",s)&& s[0] != '0'){
scanf("%s%s",a,b);
lens = strlen(s),lena = strlen(a),lenb = strlen(b);
int k = 0;
for(int i = lenb-1 ; i >= 0 ; i--) aim[++k] = (b[i]=='*')?-1:b[i]-'0';
for(int i = lena-1 ; i >= 0 ; i--) aim[++k] = (a[i]=='*')?-1:a[i]-'0';
for(int i = lens-1 ; i >= 0 ; i--) aim[++k] = (s[i]=='*')?-1:s[i]-'0';
//for(int i = 1 ; i <= k ; i++)cout <<"aim[ "<<i<<" ] = "``
<aim[i]<<endl;
MIN = MINt = 1000000010;
check();
printf("Case %d: %s %s %s\n",++ca,ts,ta,tb);
}
}
H题Hidden Music Score
题意:
给定去掉五线谱的线之后那些音符(一个八度内)旋转一定角度之后的坐标,问最开始都是什么音符,给定起始音符,
tip:
给定的时旋转之后的,求出原来的,排序
角度为-60~60且为整数,枚举即可,起始音符给定之后相对sd就一定了,检验是否1~5,相邻的检验是否1sd~5sd,且垂直距离是否sd。
#include <cstdio>
#include <iostream>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
char p[2],b[2],mp2[10];
int mp1[110],n,ca;
const double eps = 1e-4;
const double pi = acos(-1.0);
const int maxn = 30;
typedef pair<double,double>pdd;
pdd d[maxn],a[maxn];
void init(){
scanf("%s%s",p,b);
for(int i = 1; i <= n ; i++){
scanf("%lf%lf",&a[i].first,&a[i].second);
}
}
int sign(double k){
if(fabs(k) < eps) return 0;
return k > 0 ? 1:-1;
}
char ans[maxn];
void sov(){
for(int ro = -60 ; ro <= 60 ; ro++){
double ang;
ang=(double)ro*pi/180.0;
for(int j = 1;j <= n;j++){
d[j].first = a[j].first * cos(ang) + a[j].second * sin(ang);
d[j].second = -a[j].first*sin(ang) + a[j].second*cos(ang);
}
sort(d+1,d+1+n);
double sd = (d[n].second - d[1].second)/(mp1[b[0]]-mp1[p[0]]);double real = 2.0*sd;
if(sign(real-5.0) > 0 || sign(1.0-real) > 0) continue;
int j;
for(j = 2; j <= n ; j++){
double k = d[j].first-d[j-1].first,pp = (d[j].second - d[1].second);
int ct = pp/sd;
int flag = 0;
if(sign((ct-1)*sd-pp)==0) ans[j] = mp2[mp1[p[0]]+ct-1];
else if(sign(ct*sd-pp)==0) ans[j] = mp2[mp1[p[0]]+ct];
else if(sign((ct+1)*sd-pp) == 0) ans[j] = mp2[mp1[p[0]]+ct+1];
else break;
if(sign(1.0*real-k) > 0 || sign(k-5.0*real) > 0) break;
}
if(j == n+1 && ans[n] == b[0]) break;
}
printf("Case %d: %c",++ca,p[0]);
for(int i = 2; i <= n ; i++){
printf("%c",ans[i]);
}
printf("\n");
}
void pre(){
mp1['C']=0,mp1['D']=1,mp1['E']=2;mp1['F']=3,mp1['G']=4,mp1['A']=5;mp1['B']=6;
mp2[0]='C',mp2[1]='D',mp2[2]='E';mp2[3]='F',mp2[4]='G',mp2[5]='A';mp2[6]='B';
}
int main(){
pre();
while(~scanf(
"%d",&n) && n){
init();
sov();
}
}
J题Overlapping Squares :
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cmath>
using namespace std;
const int maxn = 20;
char ini[maxn][maxn],tmp[maxn][maxn];
int vis[maxn],ca;
void init(){
for(int i = 1 ; i < 5; i++){
gets(ini[i]);
// puts(ini[i]);
// cout <<endl;
}
memset(vis,0,sizeof(vis));
for(int i = 0 ; i < 5; i++){
for(int j = 0 ; j < 9 ; j++){
tmp[i][j] = ' ';
}
}
}
//void print(){
// //if(step != 1) return ;
// printf("t: \n");
// for(int i = 0 ; i < 5 ; i++){
// for(int j = 0 ; j < 9 ; j++)
// printf("%c ",t[i][j]);
// printf("\n");
// }
// for(int i = 0 ; i < 5 ; i++){
// for(int j = 0 ; j < 9 ; j++)
// printf("%c ",ini[i][j]);
// printf("\n");
// }
// int l;
// scanf("%d",&l);
//}
int check(int step){
// print(step);
for(int i = 0 ; i < 5 ; i++)
for(int j = 0 ; j < 9 ; j++)
if(tmp[i][j] != ini[i][j]) return 0;
return 1;
}
//void book(){
// for(int i = 0 ; i < 5 ;i++){
// for(int j = 0 ; j < 9 ; j++)
// t[i][j] = tmp[i][j];
// }
// print();
//}
//void re(){
// for(int i = 0 ; i < 5 ;i++){
// for(int j = 0 ; j < 9 ; j++)
// tmp[i][j] = t[i][j];
// }
// print();
//}
void tryput(int pos){
int r = pos/3;
int c = (pos%3)*2;
tmp[r+1][c] = tmp[r+2][c] = tmp[r+1][c+4] = tmp[r+2][c+4] = '|';
tmp[r][c+1] = tmp[r][c+3] = tmp[r+2][c+1] = tmp[r+2][c+3] = '_';
tmp[r+1][c+1] = tmp[r+1][c+2] = tmp[r+2][c+2] = tmp[r+1][c+3] = ' ';
}
int dfs(int step){
if(step > 6) return 0;
if(check(step)) return 1;
char t[maxn][maxn];
for(int i = 0 ; i < 5 ;i++){
for(int j = 0 ; j < 9 ; j++)
t[i][j] = tmp[i][j];
}
for(int i = 0 ; i < 9 ; i++){
if(vis[i]) continue;
vis[i] = 1;
tryput(i);
if(dfs(step+1)) return 1;
vis[i] = 0;
for(int i = 0 ; i < 5 ;i++){
for(int j = 0 ; j < 9 ; j++)
tmp[i][j] = t[i][j];
}
}
return 0;
}
int main(){
while(gets(ini[0]) && ini[0][0] != '0'){
init();
if(dfs(0)) printf("Case %d: Yes\n",++ca);
else printf("Case %d: No\n",++ca);
}
}
/*
#
_ _ _ #
| |_ _| #
|_| | #
|_ _| #
#
_ _ #
| | #
|_ _| #
#
_ _ _ _ #
|_|_|_|_|#
|_|_|_|_|#
|_|_|_|_|#
|_|_|_|_|#
_ _ #
_| |_ #
| |_ _| |#
|_| |_|#
|_ _|_|#
0
*/