1006 GCD Game
解题思路
转化为NIMI博弈,可以参照Nim博弈 · ACM Book (gitbooks.io)
因为每一次能从一个数转到任何一个质因数的位置,因此就相当于有n堆石子,每一堆石子的个数就是这个数的质因数的个数。因此先打表,将 1 0 7 10^7 107之内的数的质因数的个数先表示出来,然后用到的时候直接查询即可。
代码
#include <bits/stdc++.h>
using namespace std;
const int MAXN=1e7+10;
int prime[MAXN/2];//存储素数
bool noprime[MAXN];//用于标记是否是素数
int num[10000010];
void init()
{
memset(noprime,false,sizeof(noprime));
int sk=0;
for (int i=2; i<=MAXN; i++)
{
if (!noprime[i]){ prime[++sk]=i; num[i]=1; }
for (int j=1; j<=sk&&i*prime[j]<=10000000; j++)
{
noprime[i*prime[j]]=1;
num[i*prime[j]]=num[i]+1;
if (i%prime[j]==0) break;
}
}
}
int main()
{
init();
int t,n;
scanf("%d",&t);
while(t--)
{
int ans=0;
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
int x;
scanf("%d",&x);
ans^=num[x];
}
if(ans)
printf("Alice\n");
else
printf("Bob\n");
}
return 0;
}
1008 Square Card
解题思路
就是求两个圆之间相交的面积和大圆的面积的比值。
但是还要考虑,方形要完全能够放在这个圆里面。极端情况就是正方形的两个点与圆相交。
如图真正要求的圆的半径 = s q r t ( r 2 − ( a / 2 ) 2 ) − ( a / 2 ) =sqrt(r2-(a/2)2)-(a/2) =sqrt(r2−(a/2)2)−(a/2)。
代码
#include <bits/stdc++.h>
#define pi 3.141592653589793238462643383279
using namespace std;
typedef long long ll;
typedef struct node
{
int x;
int y;
}point;
double calc(point a, double r1, point b, double r2)//计算两圆的相交面积
{
double d = sqrt((a.x-b.x)*(a.x-b.x) + (a.y-b.y)*(a.y-b.y));
if (d >= r1+r2)
return 0;
if (r1>r2)
{
double tmp = r1;
r1 = r2;
r2 = tmp;
}
if(r2 - r1 >= d)
return pi*r1*r1;
double ang1=acos((r1*r1+d*d-r2*r2)/(2*r1*d));
double ang2=acos((r2*r2+d*d-r1*r1)/(2*r2*d));
return ang1*r1*r1 + ang2*r2*r2 - r1*d*sin(ang1);
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
double r1, x1, y1, r2, x2, y2, aa;
scanf("%lf%lf%lf%lf%lf%lf%lf", &r1, &x1, &y1, &r2, &x2, &y2, &aa);
if (r1 * r1 - aa * aa / 4 <= 0 || r2 * r2 - aa * aa / 4 <= 0)
{
cout << "0.000000" << endl;
continue;
}
point a,b;
a.x=x1;
a.y=y1;
b.x=x2;
b.y=y2;
double r3 = sqrt(r1 * r1 - aa * aa / 4) - aa / 2, r4 = sqrt(r2 * r2 - aa * aa / 4) - aa / 2;
double res = calc(a, r3, b, r4);
printf("%.6lf\n", res / (pi * r3 * r3));
}
return 0;
}
1009 Singing Superstar
解题思路
队友ac了,待补
这个思路写的很清楚杭电多校第八场8月12日补题记录_m0_52048145的博客-CSDN博客
代码
队友的ac代码,她们做出来了我就没动了。
#include <bits/stdc++.h>
#define maxn 100005
using namespace std;
char st[maxn], st1[maxn];
struct Trie {
int next[maxn << 2][26], End[maxn << 2], root, fail[maxn << 2], id;
int cnt[maxn << 2], last[maxn << 2], Len[maxn << 2];
int newnode() {
for (int i = 0; i < 26; i++) {
next[id][i] = -1;
}
Len[id] = 0;
return id++;
}
void init() {
id = 0;
root = newnode();
}
void Insert(char* str, int id) {
int len = strlen(str);
int now = root;
for (int i = 0; i < len; i++) {
if (next[now][str[i] - 'a'] == -1)
next[now][str[i] - 'a'] = newnode();
Len[next[now][str[i] - 'a']] = Len[now] + 1;
now = next[now][str[i] - 'a'];
}
End[id] = now;
Len[now] = len;
}
void build() {
queue<int>que;
int now = root;
fail[root] = root;
for (int i = 0; i < 26; i++) {
if (next[root][i] == -1) {
next[root][i] = root;
}
else {
fail[next[root][i]] = root;
que.push(next[root][i]);
}
}
while (!que.empty()) {
now = que.front();
que.pop();
for (int i = 0; i < 26; i++) {
if (next[now][i] == -1)
next[now][i] = next[fail[now]][i];
else {
fail[next[now][i]] = next[fail[now]][i];
que.push(next[now][i]);
}
}
}
}
void query(char* str) {
int len = strlen(str);
for (int i = 0; i < id; i++) cnt[i] = 0, last[i] = -1;
int now = root;
for (int i = 0; i < len; i++) {
now = next[now][str[i] - 'a'];
int tmp = now;
while (tmp != root) {
if (i - last[tmp] >= Len[tmp]) {
cnt[tmp]++;
last[tmp] = i;
}
tmp = fail[tmp];
}
}
}
}ac;
int main()
{
int n, m;
int t;
scanf("%d", &t);
while (t--)
{
scanf("%s", st);
n = strlen(st);
scanf("%d",&m);
ac.init();
for (int i = 1; i <= m; i++) {
scanf("%s", st1);
ac.Insert(st1, i);
}
ac.build();
ac.query(st);
for (int i = 1; i <= m; i++) {
printf("%d\n", ac.cnt[ac.End[i]]);
}
}
return 0;
}