链接: CF40A Find Color
代码:
#include
using namespace std;
int x,y,l,r;
int main()
{
cin>>x>>y;
l=x*x+y*y;
r=sqrt(l);
if(r*r==l)cout<<"black"<<endl;
else cout<<((r%2==0)^(x*y<0)?"black":"white")<<endl;
return 0;
}
链接:45I TCMCF++
题意: 给出n个问题,总积分为解决问题积分的乘积。可自由选择解决多少问题,最大化总积分。
题解: 对于问题的积分,正数全都取,0不取,负数取最多的偶数个,排序遍历即可。
代码: 签到题,咕。
链接:1096C Polygon for the Angle
题意: 给出一个整数的角度,要求找出一个正n边形,使得其中三个顶点可以得去该角度。
题解: 对于一个正n边形,其中所有可能的角度 a n g = 180 ° ⋅ k n ( 1 ≤ k ≤ n − 2 ) ang=\frac{180°·k}{n}(1 \le k \le n-2) ang=n180°⋅k(1≤k≤n−2),数据范围较小,直接暴力枚举n即可。
证明: 将正多边形放入外接圆,由等边对等角可得证一点到其他点连线后所得角是相等的,即 n − 2 n-2 n−2个三角形。
代码: 解法较多,可以多观摩借鉴不同方法。
链接:CF 197A Plate Game
题意: 你有一张长a宽b的长方形桌子,桌子上有半径为r的无限多的盘子,两个玩家玩下面的游戏:他们轮流把盘子放在桌子上,使盘子之间不躺在一起(但可以互相接触),并使任何盘子上的任何一点都位于桌子的边界内。在游戏过程中,不能移动已经躺在桌子上的盘子。不能再移动的棋手即为输家。决定哪位棋手获胜,是先移动的棋手还是后移动的棋手,前提是两位棋手都能发挥出最佳水平。
题解: 只要第一个人可以放下盘子则必胜。第一个人将盘子放在桌子中心,如果第二个人可以采取行动,第一个人采取对称的行动即可。
代码:
#include
using namespace std;
int a,b,r;
int main()
{
cin>>a>>b>>r;
if(r*2>min(a,b))cout<<"Second"<<endl;
else cout<<"First"<<endl;
return 0;
}
链接:224A Parallelepiped
题意: 你有一个边长为整数的矩形平行六面体。你知道它有一个公共顶点的三个面面积。你的任务是找出这个平行六面体所有12条边的长度之和。
题解: 设六面体的共点三边为 a , b , c , a,b,c, a,b,c,则六面体的三个面积为 s 1 = a ∗ b , s 2 = a ∗ c , s 3 = b ∗ c s_1=a*b,s_2=a*c,s_3=b*c s1=a∗b,s2=a∗c,s3=b∗c,即 a = s 1 ⋅ s 2 s 3 , b = s 1 ⋅ s 3 s 2 , c = s 2 ⋅ s 3 s 1 a=\sqrt \frac{s_1·s_2}{s_3},b=\sqrt \frac{s_1·s_3}{s_2},c=\sqrt \frac{s_2·s_3}{s_1} a=s3s1⋅s2,b=s2s1⋅s3,c=s1s2⋅s3
代码:
#include
using namespace std;
int a,b,c,ans;
int main()
{
cin>>a>>b>>c;
ans=4*(sqrt(a*b/c)+sqrt(a*c/b)+sqrt(b*c/a));
cout<<ans;
return 0;
}
链接:1452D Radio Towers
题意: 在一条坐标线上有n+2个城镇,编号从0到n+1。第i个城镇位于i点。
你在每一个城镇1,2,…,n建立一个无线电塔,概率为 1 2 \frac{1}{2} 21(这些事件是独立的)。之后,你要将每个塔上的信号功率设置为1到n的某个整数(信号功率不一定相同,但也不一定不同)。位于城市i的信号塔的信号功率为p,到达每个城市c,这样 ∣ c − i ∣ < p |c-i| ∣c−i∣<p
建好塔后,你要选择信号功率的方式,使。
城镇0和n+1不会从无线电塔上得到任何信号。
城镇1,2,…,n各从一个无线电塔获得信号。
例如,如果n=5,你在2、4、5三个镇建了铁塔,可以将2镇的铁塔信号功率设为2,4、5镇的铁塔信号功率设为1,这样,0和n+1镇得不到任何铁塔的信号,1、2、3镇得到2镇铁塔的信号,4镇得到4镇铁塔的信号,5镇得到5镇铁塔的信号。
计算建好铁塔后,信号功率满足所有约束条件的概率。
题解: 规律类似于斐波那契数列, d p [ 1 ] = d p [ 2 ] = 1 , d p [ n ] = d p [ n − 1 ] + d p [ n − 2 ] ( n > 2 ) dp[1]=dp[2]=1,dp[n]=dp[n-1]+dp[n-2](n>2) dp[1]=dp[2]=1,dp[n]=dp[n−1]+dp[n−2](n>2)
思路1:
可以想到,不管信号强度为多少,该信号塔能覆盖到的数量一定是奇数。
题目就转变为 d p ( i ) 2 n \frac{dp(i)}{2^n} 2ndp(i) ,其中 d p ( i ) dp(i) dp(i) 表示 i i i能被拆成奇数的方案个数。(注意这里是顺序可换的方案)
比如 d p ( 3 ) = 2 dp(3)=2 dp(3)=2,因为 3 = 1 + 1 + 1 = 3 3 = 1 + 1 + 1 = 3 3=1+1+1=3
考虑状态转移方程就可以了:
d p ( i ) = d p ( i − 1 ) + d p ( i − 3 ) + ⋯ + d p ( ( x − ( 2 k + 1 ) ) > 0 ) dp(i)=dp(i-1)+dp(i-3)+\cdots+dp((x-(2k+1))>0) dp(i)=dp(i−1)+dp(i−3)+⋯+dp((x−(2k+1))>0)
就用一个前缀和 p r e [ x ] = d p ( x ) + d p ( x − 2 ) + ⋯ pre[x]=dp(x)+dp(x-2)+\cdots pre[x]=dp(x)+dp(x−2)+⋯ 就可以了。【鸣谢@溢流眼泪】
代码:
#include
using namespace std;
#define mod 998244353
#define ll long long
ll quickpow(ll a,ll b)//快速幂板子
{
if(b<0)return 0;
ll ret=1;
a%=mod;
while(b)
{
if(b & 1 ) ret = ( ret *a ) % mod;
b>>=1;
a = (a * a)% mod;
}
return ret;
}
ll inv(ll a)//逆元板子
{
return quickpow(a,mod-2);
}
ll n,p,ans;
ll dp[200500];
int main()
{
cin>>n;
dp[1]=dp[2]=1;
for(int i=3;i<=n;i++)dp[i]=(dp[i-1]+dp[i-2])%mod;
p=quickpow(2,n);
ans=dp[n]*inv(p)%mod;
cout<<ans<<endl;
return 0;
}
链接:35D Animals
题意: 有某种动物,可以在农场中待n天,如果它是第i天来的话,从第i天到第n天每天要吃的食物为a[i],这些动物可以中途来,不可以中途走,问最多能容纳多少只动物
题解: 贪心,预处理动物第i天来时总共需要消耗的食物,sort排序后从小的开始选。
代码:
#include
using namespace std;
int n;
int k;
int a[1000000];
int cnt=1;
int ans;
int main()
{
freopen("input.txt","r",stdin);
freopen("output.txt","w",stdout);
cin>>n>>k;
for(int i=1;i<=n;i++)
{
cin>>a[i];
a[i]=a[i]*(n-i+1);//n-i+1是剩余天数,处理后的a[i]
}//即为第i天来的动物所需要的粮食
sort(a+1,a+n+1);
while(k-a[cnt]>=0&&cnt<=n)//从小的开始选
{
ans++;
k-=a[cnt++];
}
cout<<ans<<endl;
return 0;
}
链接:1241D Sequence Sorting
题意: 对于一个序列,每次操作可以把所以相同的数字挪到队首或者队尾。问最少操作几次可以保证这个序列是一个非降序列。
题解:
网络题解:我们只需要记录一个元素的第一次出现的位置和最后一次出现的位置然后记录有多少不同的元素。我们不找需要操作的元素,找不用操作的元素,用总的元素减去不用操作的就是答案。
个人题解:对于相同的数字,我们可以当成一个整体。将序列排序,记录每个数字的左右出现的位置(当成线段)。如果 A < B , A r > B l , AB_l, A<B,Ar>Bl,即线段相交,说明 A 、 B A、B A、B位置有逆序的部分,需要重排1次A或B,当时如果 A < B , A r < B l , AA<B,Ar<Bl,且 A 、 B A、B A、B相邻,可以说明 A 、 B A、B A、B是有序的,即 A 、 B A、B A、B可视为一个整体。我们用总共的数字(不重复)数减去最大的一段有序部分数字数,即为答案(剩余的无序数字)。
代码:
#include
using namespace std;
#define ll long long
struct node
{
int v,id;
}a[300500];
bool cmp(node a,node b)
{
if(a.v==b.v)return a.id<b.id;
return a.v<b.v;
}
int l[300500],r[300500];
int T,n,cnt,key,t;
int main(){
cin>>T;
while(T--)
{
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>a[i].v;
a[i].id=i;
}
sort(a+1,a+1+n,cmp);//将原数组按值、位置排序
cnt=1;
for(int i=1;i<n;i++)
{
if(a[i].v!=a[i+1].v)r[cnt]=a[i].id,l[++cnt]=a[i+1].id;
}//记录每个数最左、最右的位置;
key=1;t=1;
for(int i=1;i<cnt;i++)
{
if(r[i]>l[i+1])key=1;
else key++;
t=max(t,key);
}
cout<<cnt-t<<endl;
}
return 0;
}
链接:166E Tetrahedron
题意: 一只蚂蚁站在一个正四面体的顶点D上,求走过n(1≤n≤1e7)条棱后回到原顶点的方案总数对1e9+7取模。
思路: dp,可打表找规律。
f[i]表示走i步回到原点的方案数,g[i]表示走i步回到不原点的方案数。
f[i]=g[i−1]×3,g[i]=f[i−1]+g[i−1]×2
代码:
#include
using namespace std;
long long n;
long long f1={
1};
long long f2;
int main(){
long long i,j,n;
cin>>n;
for(i=1;i<=n;i++){
long long x,y;
x=f1;y=f2;
f1=y*3%1000000007;
f2=(x+y*2)%1000000007;
}
cout<<f1<<endl;
return 0;
}
链接:550C Divisibility by Eight
题意: 给你一个长度最大为100的整数,问你能不能去掉这个整数里面的数字,使去掉后的整数能被8整除。
思路: 一个数要是能被8整除,只需满足后三位能被8整除。暴力寻找长度和 k = 1 , 2 , 3 k=1,2,3 k=1,2,3位数字,k位数字和为8即满足要求。
祝大家回家快乐,听说明天难度又要开始回归了~~~