B. Fraction
签到题,数据范围极小,一个一个模拟就好。
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
int n, a[15], b[15];
#define LL long long
LL ans1, ans2;
void f1(int x)
{
ans1 = ans1 + ans2 * x;
}
void f2(int x)
{
swap(ans1, ans2);
ans1 *= x;
}
LL gcd(LL x, LL y)
{
return y ? gcd(y, x%y) : x;
}
int main()
{
int t, i, ca = 1;
scanf("%d", &t);
while (t--&&scanf("%d", &n))
{
for (i = 1; i <= n; i++)
scanf("%d", a + i);
for (i = 1; i <= n; i++)
scanf("%d", b + i);
ans1 = b[n], ans2 = a[n];
for (i = n - 1; i > 0; i--)
f1(a[i]), f2(b[i]);
long long te = gcd(ans1, ans2);
printf("Case #%d: %lld %lld\n", ca++, ans1 / te, ans2 / te);
}
}
D.Triangle
也是数据范围极小的签到题,手动打表就行。
#include<cstring>
#include<cstdio>
int a[] = { 1,2,3,5,8,13,21 };
int main()
{
int n, t, ca = 1;
scanf("%d", &t);
while (t--&&scanf("%d", &n))
{
int sum = 0;
for (int i = 1; i <= n; i++)
for (int j = 0; j < 7; j++)
if (i == a[j])
sum++;
printf("Case #%d: %d\n", ca++, n - sum);
}
}
H Sequence I
智障的把b中插入任意数,然而怎样都ac不了..
只要分段做p次kmp就行,复杂度O(n+m)。(手机上改的代码ac的..)
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
#define mm 1000005
int a[mm], b[mm], ne[mm];
int main()
{
int t, i, j, ca = 1, n, m, p;
scanf("%d", &t);
while (t--&&scanf("%d%d%d", &n, &m, &p))
{
for (i = 0; i < n; i++)
scanf("%d", a + i);
for (i = 0; i < m; i++)
scanf("%d", b + i);
if (1 + (m - 1)*p > n)
{
printf("Case #%d: 0\n", ca++);
continue;
}
memset(ne, 0, sizeof(ne));
int x = m, y = n, z;
j = 0;
for (i = 1; i < x; i++)//O(x)
{
while (j > 0 && !(b[i] == b[j]))
j = ne[j];
if ((b[i] == b[j]))
j++;
ne[i + 1] = j;
}
j = 0, z = 0;
for (int k = 0; k<p; k++)
for (i = k, j = 0; i < y; i += p)//O(y)
{
while (j > 0 && !(a[i] == b[j]))
j = ne[j];
if ((a[i] == b[j]))
j++;
if (j == x)
z++, j = ne[j];
}
printf("Case #%d: %d\n", ca++, z);
}
}
F Harmonic Value Description
构造一个公式值第k小的序列,special judge。
显然公式可能的值是连续的从n-1,开始的整数注意2*k<=n(实际k是可以更大的),所以构造的时候只要构造出一个非1的数,其他相邻的数全部互质就好。
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
int main()
{
int t, n, k, ca = 1;
scanf("%d", &t);
while (t--)
{
scanf("%d%d", &n, &k);
printf("Case #%d: ", ca++);
for (int i = 1; i <= k; i++) printf("%d ", i);
for (int i = 2 * k; i >= k + 2; i--) printf("%d ", i);
printf("%d", k + 1);
if ((2 * k + 1) > n)
{
printf("\n");
continue;
}
else
{
for (int i = 2 * k + 1; i <= n; i++)
printf(" %d", i);
}
printf("\n");
}
}
J Ugly Problem
把一个1000位以内的数拆成50个以内的回文数的和,special judge。
可以想到贪心的构造小于等于x的最大回文数(不是最大也行,尽量大就好)。
一个构造方法是取数位大的一半-1,小的一半与前一半对称(比如255321就是254452)。显然这样一个n位数减去这个回文数之后最多还有n/2+1位。总体复杂度是O(logn)的(但这个策略不一定是最大的回文数)
还有一些细节..比如10和11,1000之类..注意一下就好。
用c++就要手写大数减法(好在不会减到负数),用java大数写也行。
import java.util.*;
import java.math.*;
class my{
public static boolean jud(BigInteger x)
{
while(x.compareTo(BigInteger.ZERO)!=0)
{
if((x.mod(BigInteger.TEN)).compareTo(BigInteger.ZERO)!=0)
return false;
x = x.divide(BigInteger.TEN);
if(x.compareTo(BigInteger.TEN)==0)
break;
}
return true;
}
public static boolean jud2(BigInteger x)
{
String ss = x.toString();
char[] cc = new char[1000];
cc = ss.toCharArray();
int len=cc.length;
for(int i=0;i<len/2+1;i++)
if(cc[i]!=cc[len-1-i])
return false;
return true;
}
}
public class Main
{
public static void main(String[] args)
{
Scanner in = new Scanner(System.in);
BigInteger a, b;
BigInteger[] ans = new BigInteger[55];
String ss;
int len, anslen = 0, t, cnt = 0;
char[] cc, nn, yy;
char temp1, temp2, minn;
cc = new char[1005];
yy = new char[1005];
t = in.nextInt();
while(t != 0)
{
t--;
cnt++;
anslen=0;
a = in.nextBigInteger();
while(a.compareTo(BigInteger.ZERO)!=0)
{
if(a.compareTo(BigInteger.TEN)==0)
{
ans[anslen++]=BigInteger.TEN.subtract(BigInteger.ONE);
ans[anslen++]=BigInteger.ONE;
break;
}
if(a.compareTo(BigInteger.TEN)<0)
{
ans[anslen++]=a;
break;
}
if(a.compareTo(BigInteger.TEN.add(BigInteger.ONE))==0)
{
ans[anslen++]=a;
break;
}
ss = a.toString();
cc = ss.toCharArray();
nn = ss.toCharArray();
len = cc.length;
int lent;
if(len%2==0)
lent=len/2;
else
lent=len/2+1;
StringBuffer tt = new StringBuffer();
for(int i = 0; i<lent; i++)
tt.append(cc[i]);
BigInteger tempb1 = new BigInteger(tt.toString());
if(my.jud(tempb1)) //999999
{
nn = new char[len-1];
for(int j=0;j<len-1;j++) nn[j]='9';
}
else
{
if(tempb1.compareTo(BigInteger.ONE)!=0)
tempb1 = tempb1.subtract(BigInteger.ONE);
ss = tempb1.toString();
yy = ss.toCharArray();
int len2 = (yy.length)*2;
if(len2>len)
len2=len;
nn = new char[len2];
for(int i=0;i<yy.length;i++)
{
nn[i]=yy[i];
nn[len2-i-1]=yy[i];
}
}
String temps1 = new String(nn);
String temps2 = new String(cc);
BigInteger tempbx = new BigInteger(temps1);
BigInteger tempbj = new BigInteger(temps2);
BigInteger tempbn;
tempbn = tempbj.subtract(tempbx);
ans[anslen++] = tempbx;
a = tempbn;
}
System.out.printf("Case #%d:\n",cnt);
System.out.println(anslen);
for(int i=0;i<anslen;i++)
System.out.println(ans[i]);
}
}
}