1004 Laser Beam
一道很纠结的题,最初打算从角度入手,可是始终无法找到好的方法。后来发现可以把给出的大三棱镜划分为多个小三角形,每个小三角形中与入射点对称的点则是入射光线可能到达的点。
之后,我们将三角形进一步缩小后就能找出每一次入射不同角度的变化,进一步能发现如果反射n次则反射点必在第(n+3)/2行(指小三角形的行数)
之后只要找出并去重和去除不成立的点就能出结果了。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <string>
#include <vector>
#include <queue>
#include <map>
using namespace std;
int n,s,shu,ans;
int pr[1005];
void change(int wei,int shug,int ch)
{
if(wei == shu)
{
int get = (shug % 3) * (n % 3) % 3 * shug;
if(s >= get)
ans += ((s - get) / 3 / shug + 1) * ch;
}
else
{
change(wei+1,shug,ch);
change(wei+1,shug*pr[wei],-ch);
}
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
if(n % 2 == 0 || n % 3 == 0)
{
printf("0\n");
continue;
}
s = (n + 3) / 2;
shu = 0;
for(int i=2;i*i<=s;i++)
{
if(s % i == 0)
{
pr[shu] = i;
while(s % i == 0)
{
s = s / i;
}
shu++;
}
}
if(s != 1)
{
pr[shu] = s;
shu++;
}
ans = 0;
s = (n + 3) / 2;
change(0,1,1);
printf("%d\n",ans);
}
return 0;
}
1005 Another Graph Game
一道很伤心的刷版题,在此膜拜宝哥的YY能力^_^
题目说的好像很复杂,又有点又有边的,但是,如果我们把边拆开分给对应的两个点的话,那么就变成了单纯的数组排序问题。
可惜我这样的题竟然还因为数据范围的问题W了两次,伤心啊T_T
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <string>
#include <vector>
#include <queue>
#include <map>
using namespace std;
int n,m;
double s[100005];
int u,v;
double w,ans;
bool cmp(double x,double y)
{
return x > y;
}
int main()
{
while(scanf("%d%d",&n,&m) != EOF)
{
for(int i=0;i<n;i++)
{
scanf("%lf",&s[i]);
}
for(int i=0;i<m;i++)
{
scanf("%d%d%lf",&u,&v,&w);
s[u-1] += w / 2.0;
s[v-1] += w / 2.0;
}
sort(s,s+n,cmp);
ans = 0;
for(int i=0;i<n;i += 2)
{
ans += s[i] - s[i + 1];
}
printf("%.0lf\n",ans);
}
return 0;
}
1006Magic Pen 6
又是一道刷版题。
目测是因为数据比较水的关系,N^2的算法也一样过,用存取模数的方法来做也仅仅只是压缩了点时间而已,不多说了。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <string>
#include <vector>
#include <queue>
#include <map>
using namespace std;
int n,m,sum,ans;
int s[100005];
int mo[10005];
int main()
{
while(scanf("%d%d",&n,&m) != EOF)
{
sum = 0;
ans = 0;
memset(mo,-1,sizeof(mo));
mo[0] = 0;
for(int i=0;i<n;i++)
{
scanf("%d",&s[i]);
sum += s[i];
sum = (sum % m + m) % m;
if(mo[sum] == -1)
{
mo[sum] = i + 1;
}
else
{
if(i + 1 - mo[sum] > ans)
{
ans = i + 1 - mo[sum];
}
}
}
printf("%d\n",ans);
}
return 0;
}
1009Partition
一道老题,规律之类的网上有好多,只要按五角数来进行预处理就能很简单的输入输出了。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <string>
#include <vector>
#include <queue>
#include <map>
using namespace std;
#define mod 1000000007
long long int f[100001];
long long int f1[100001];
long long p[100001];
void ff()
{
int i;
for(i=0;i<=5000;i++)
{
f[i]=i*(3*i-1)/2;
f1[i]=f[i]+i;
}
}
void pp()
{
memset(p,0,sizeof(p));
p[0]=1;
p[1]=1;
p[2]=2;
p[3]=3;
p[4]=5;
int i,j;
for(i=5;i<=100001;i++)
{
int ans=1;
for(j=1;;j++)
{
if((i-f[j])<0&&(i-f1[j])<0)
break;
if((i-f[j])>=0)
p[i]=(p[i]+(ans*p[i-f[j]])+mod)%mod;
if((i-f1[j])>=0)
p[i]=(p[i]+(ans*p[i-f1[j]])+mod)%mod;
ans*=(-1);
}
}
}
int main()
{
ff();
int T;
int i,j;
int n;
pp();
scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
printf("%I64d\n",(p[n]+mod)%mod);
}
return 0;
}
1011k-th point
多面球体问题,代码很简单,但是中间的推规律的过程很伤心。
有兴趣的可以自己上网找推的过程,是一个很有趣的过程。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <string>
#include <vector>
#include <queue>
#include <map>
using namespace std;
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
double p,n,k;
scanf("%lf%lf%lf",&p,&n,&k);
double s=1.0;
for(int i=n-k; i<=n; i++)
{
s*=(i*p/(i*p+1));
}
printf("%.9lf\n",s);
}
return 0;
}