1001:
首先,我们统计出Derek和Alfia答案相同的题目数量k1和答案不同的题目数量k2. 对于两人答案相同的题目,共有以下两种情况:
- 两人都对
b.两人都错 对于两人答案不同的题目,共有以下三种情况: c.Derek对Alfia错 d.Alfia对Derek错 e.两人都错 于是我们可以列出一些方程: k1+k2=n a+b=k1 c+d+e=k2 a+c=x a+d=y 又a,b,c,d,e均为非负整数,且满足a,b<=k1;c,d,e<=k2 将a,b,d,e全部用c替换后需要同时满足以下四个条件: 0<=c<=k2 x-y<=c<=k2+x-y (x-y)/2<=c<=(k2+x-y)/2 x-k1<=c<=x 我们只需要判断这四段区间存不存在公共的整数点,如果存在,则说明Derek没有说谎;如果不存在,则说明Derek在说谎。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#include <cmath>
#include <algorithm>
#include <deque>
using namespace std;
typedef long long ll;
const int INF = 2147483640;
const int maxn = 80000 + 100;
const int maxm = 200000;
char ar[maxn], sa[maxn];
int main()
{
int i, j, k, u, n, m, A, B, N;
while (scanf("%d", &n) != EOF)
{
for (m = 1; m <= n; m++)
{
int doudou1 = 0;
int doudou2 = 0;
scanf("%d %d %d", &N, &A, &B);
scanf("%s", ar);
scanf("%s", sa);
for (i = 0; i < N; i++)
{
if (ar[i] == sa[i])
doudou1++;
else
doudou2++;
}
if (A + B <= (doudou2 + doudou1 * 2) && doudou2 >= abs(A - B))
printf("Not lying\n");
else
printf("Lying\n");
}
}
return 0;
}
1003:
预处理:a_i -= i ,易证明从最小的b开始选每次选最大的一定可以使结果最大。 证明思路:如果条件改为a_i<=max{a_j-j|b_k<=j<=n},那么b的顺序与最后的结果无关。条件改回来后,由于每次要计算一个数的最大值时都有a_(n+1)...a_(i-1)在范围中,所以每次只需让a_i - i尽可能大,那么就把大的数尽早用上,每次一定考虑尽量多的数字,这样取得的数字就尽可能的大。 所以说每次就是求区间最值,加在答案上。由于贪心的思路,每次要求的区间的下界是单调不降的,故可以用单调队列优化到O(n)的复杂度。 由于1 ≤ b_i ≤ n,对b排序可以用哈希排序(桶排序)完成。 进一步观察,可以发现这样贪心时 a_(n+1)...a_i 其实是单调不增的,所以并不需要每次求区间最值了,选第一个数时就选最大的,后面的选择顺序与最终结果无关了。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll MOD = 1e9+7;
int a[300000];
int b[300000];
struct node{
int a,id;
};
struct cmp{
bool operator ()(const node &a,const node &b){
return a.a<b.a;
}
};
priority_queue< node ,vector<node > ,cmp> Q;
int main(){
int n;
while(~scanf("%d",&n)){
for(int i=1;i<=n;i++)
scanf("%d",a+i);
for(int i=1;i<=n;i++)
scanf("%d",b+i);
for(int i=1;i<=n;i++)
a[i]-=i;
int tmx = a[n];
while(!Q.empty()) Q.pop();
sort(b+1,b+1+n);
ll ans = 0;
for(int i=1;i<=n;i++){
Q.push(node{a[i],i});
}
int t=0;
for(int i=n+1;i<=n+n;i++){
while(Q.top().id<b[i-n]) Q.pop();
node now = Q.top();
ans += now.a;
ans %= MOD;
Q.push(node{now.a-i,i});
}
cout<<ans<<endl;
}
return 0;
}
1006:
对于任意i>=1,当j>=3时,有 通过归纳法可以得到 进而推导出 通过矩阵快速幂求解
1011:
题意,二维平面上给N个整数点,问能构成多少个不同的正多边形。 题解:容易得知只有正四边形可以使得所有的顶点为整数点。(具体证明可参考杨景钦在2017的国家队论文) 所以正解即求出所有的正四边形个数。 枚举2个点,然后暴力判断另外2个点的位置是否存在。 复杂度 N*N*logN。
#include <bits/stdc++.h>
using namespace std;
struct node{
int x,y;
}info[1000];
int mp[402][402];
int p[402][402];
int main(){
int n;
while(~scanf("%d",&n)){
memset(mp,0,sizeof mp);
memset(p,0,sizeof p);
int mx=0,my=0;
for(int i=1;i<=n;i++){
scanf("%d%d",&info[i].x,&info[i].y);
info[i].x+=100;
info[i].y+=100;
mp[info[i].x][info[i].y]=1;
}
int ans = 0;
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++){
if(info[i].x>=info[j].x || info[i].y>=info[j].y) continue;
int nx = info[i].x;
int ny = info[i].y;
int l = info[j].x - nx;
int s = info[j].y - ny;
if(l==s && mp[nx+l][ny] && mp[nx][ny+s] && mp[nx+l][ny+s]){
ans++;
}
int sx = nx - (info[j].y - ny);
int sy = ny + (info[j].x - nx);
int tx = sx + (info[j].x - nx);
int ty = sy + (info[j].y - ny);
if(mp[sx][sy] && mp[tx][ty]){
ans++;
}
}
cout<<ans<<endl;
}
return 0;
}