面积和

时间限制: 1 Sec 内存限制: 128 MB
[提交] [状态]
题目描述
平面上有N个点,求出所有以这N个点为顶点的三角形的面积和。
输入
第一行一个正整数N,表示点数。
下面N行给出N个点的坐标,坐标值均为[0,10000]的整数。
输出
输出答案,保留一位小数,误差不超过0.1。
样例输入 Copy
5
0 0
1 2
0 2
1 0
1 1
样例输出 Copy
7.0
提示
对于100%的数据,满足1≤n≤2000

并没有学计算几何,所以就直接放博客

数学难题

时间限制: 1 Sec 内存限制: 128 MB
[提交] [状态]
题目描述
学佛Fife最喜欢Bemy上的数学课了。因为他可以在数学课上尽情的蒸发学水~
Bemy为了不让学佛Fife过度骄傲,以保证每一个学水都能不被他影响,自信地不断地进步,给Fife一个有挑战性的数学题。
因为Fife不想让妹子Maze等得太久,决定把这道题交给你。

题目是这样的:有一个表达式(B+E+S+S+I+E)(G+O+E+S)(M+O+O)
其中B,E,S,I,G,O,M为七个变量(注意“O”是变量不是0)。
对于每个变量,Bemy会告诉Fife这个变量所代表的各个可能值。
Bemy想问问Fife这样一个问题:原表达式有多少种可能的情况,使表达式的值为偶数。(只要有一个变量的值不同,即为一种情况)

输入
第一行输入包含一个整数N。
下一个N 行每行包含一个变量名称和一个这个变量可以使用的值。
注:每个变量在整张表中不会出现多于20 次。
同一个变量不存在两个相同的值。所有给出的值都在-300……300 之间。

输出
打印出一个整数,表示有多少种方法使表达式的值为一个偶数。
样例输入 Copy
10
B 2
E 5
S 7
I 10
O 16
M 19
B 3
G 1
I 9
M 2
样例输出 Copy
6
提示
样例解释
(B,E,S,I,G,O,M)=(2,5,7,10,1,16,19)->53,244
=(2,5,7,10,1,16,2)->35,496
=(2,5,7,9,1,16,2)->34,510
=(3,5,7,10,1,16,2)->36,482
=(3,5,7,9,1,16,19)->53,244
=(3,5,7,9,1,16,2)->35,496
【数据规模】
对于30%的数据,N<=60。
对于100%的数据,N<=140。

题意:

给定七个变量中某些变量可取的值,求使得表达式结果为偶数时的方案数

思路:

因为奇数+奇数=偶数,奇数+偶数=奇数等等
所以所有奇数对答案的贡献是相同的,所有偶数对答案的贡献是相同的。
其实这个数实际的值并没有很大意义,只需要考虑这个数是奇数还是偶数即可。
如果当前变量的奇偶取值使得表达式满足,该部分的方案数就是当前每个变量可能取值的个数的乘积。(乘法原理)

代码:
极度"美丽"的for循环(狗头.jpg)

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
 
const int maxn=1100;
 
int a[maxn][2];
///0偶数 1奇数
 
bool check(int B,int E,int S,int I,int G,int O,int M){
    if((B+E+S+S+I+E)*(G+O+E+S)*(M+O+O)%2==0) return 1;
    return 0;
}
int main(){
    int n;cin>>n;
    char ch;int tmp;
    while(n--){
        getchar();
        cin>>ch>>tmp;
        ///cout<<ch<<" "<<tmp<<endl;
        if(tmp%2) a[ch-'A'][1]++;
        else a[ch-'A'][0]++;
    }
    int res=0;
    ///B,E,S,I,G,O,M
    for(int B=0;B<=1;B++)
        for(int E=0;E<=1;E++)
            for(int S=0;S<=1;S++)
                for(int I=0;I<=1;I++)
                    for(int G=0;G<=1;G++)
                        for(int O=0;O<=1;O++)
                            for(int M=0;M<=1;M++)
                                if(check(B,E,S,I,G,O,M))
                                    res=res+(a['B'-'A'][B]*a['E'-'A'][E]*a['S'-'A'][S]*a['I'-'A'][I]*a['G'-'A'][G]*a['O'-'A'][O]*a['M'-'A'][M]);
 
    cout<<res<<endl;
    return 0;
}

学佛和学水

时间限制: 1 Sec 内存限制: 128 MB
[提交] [状态]
题目描述
世界上存在2种人,学佛和学水……尽管他们考试都能得很高的分。
他们之间唯一的不同就是:学佛考试总是能独立完成,轻松AK,并且不屑于与学水为伍,他的佛光可以笼罩左右的同学,并且距离越远,佛光的作用越低。而学水考试的时候总会喜欢散发出与佛光能量相同的学水来吸引周围的同学一起作弊(合作)。
Fife所在的学校考试时,学生们所在的考场座位是排成一行,座位号L~R的顺序依次排列的。假设Fife的座位号为x,Bemy的座位号为y,则他们之间的距离为|x-y|。
考场上总有许多为学佛和学水,但更多的是一些普通学生。普通学生们总是会被周围的学佛和学水所左右迷惑。设每位普通学生离和他最近的学佛的距离为dis1, 和离他最近的学水的距离为dis2。如果dis1<dis2,则这位同学就会被佛光所笼罩,就有了与学佛相同的本领(能够独立完成,轻松AK)。如果dis1 >= dis2,则这位同学就会加入学水的队伍中,考试时就会一起合作(由于水的比热容较大,能够抵御强大的佛光,所以当dis1=dis2时,这位同学考试时也会和学水们合作)。
Fife作为远近闻名的大学佛,他容忍不了那些作弊(合作)的行为,所以他想让你告诉他,参加考试的人里面,有多少个人在考试的时候作弊(合作)。

输入
第一行三个数,n,l,r。n为学佛或学水的个数,l,r为所有考生的座位号。
接下来有n行,每行要么是‘NS x’,表示座位号为x的考生为学佛。
要么是‘S x’,表示座位号为x的考生为学水。

输出
一行一个整数n,表示***(合作)的人数。
样例输入 Copy
3 1 10
S 10
NS 4
S 1
样例输出 Copy
6
提示
样例解释
1,2,7,8,9,和10是作弊(合作)的人。

【数据规模】
对于40%的数据,1<=L<=R<=10,000,000。
对于100%的数据,N<=50,000,1<=L<=R<=1,000,000,000,L<=x<=R
题意:

每个普通学生可能会受到学水或学佛影响,统计所有受到学水影响以及所有学水的个数。

思路:
一开始想了个贼sb的思路把自己卡死了
先说之前的思路:
对于每一个学佛,二分查找位置小于它的最后一个学水和位置大于它的第一个学水,统计之间的数量。但是这样会造成计算重复,所以如果前一个学佛的坐标大于前一个学水坐标的话就不考虑,如果后一个学佛的坐标小于后一个学水坐标的话,就考虑进去。

可能这大体是对的?反正写完调bug调的心态炸了。。

比较好写的思路就是直接遍历n,然后分类讨论这个和上一个的情况,总共是四种情况。
要注意一下特判开头和结尾的情况,因为每一个点都是向前覆盖的,所以a[n].pos 到 r 那部分并不会被处理。因为处理a[1].pos的时候并没有上一个,所以也要特殊处理一下。

再来看一下如何计算之间的数量。
假设当前坐标是b , 上一个坐标是 a
如果当前和上一个都是学水时,数量就是a~b之间的数,例如a=1,b=3,数量就是1,即b-a-1.(因为是把学水单独拿出来计算的)
如果当前是学水,上一个是学佛时:
比如a=1,b=4 那么只有3是符合题意的,数量为1
比如a=1,b=5,那么3,4都是符合题意的数量为2
综上,数量是(b-a)/2;

代码:
过于繁杂。。

#include<bits/stdc++.h>
typedef long long ll;
using namespace std;
 
const int maxn=1e6+7;
 
struct node{
    ll pos;
    int flag;
}a[maxn];
int cnt=0;
 
bool cmp(node a,node b){
    return a.pos<b.pos;
}
 
int main(){
    ll n,l,r;
    scanf("%lld%lld%lld",&n,&l,&r);
    char ch[5];
    ll tmp;
    ll tot_s=0;
    for(int i=1;i<=n;i++) {
        cin>>ch>>tmp;
        ///cout<<ch<<tmp;
        if(ch[0]=='S'){///学水
            a[i]={tmp,0};
            tot_s++;
        }
        else{
            a[i]={tmp,1};///学佛
        }
    }
    sort(a+1,a+1+n,cmp);
    ///计算离得学水近的人数是多少
    ll res=0;
    ll last=-1;
    ///学水是0 学佛是1
    for(int i=1;i<=n;i++){
        if(last==-1){
            if(!a[i].flag) res+=a[i].pos-l;
        }
        else{
            if(!a[i].flag){///这个是学水
                if(!last){///如果前一个也是学水
                    res+=a[i].pos-a[i-1].pos-1;
                }
                else{
                    ll tt=a[i].pos-a[i-1].pos;
                    res+=tt/2;
                }
            }
            else{///这个是学佛
                if(!last){///如果前一个是学水
                    ll tt=a[i].pos-a[i-1].pos;
                    res+=tt/2;
                }
                /*else{///如果前一个是学佛 }*/
            }
        }
        last=a[i].flag;
    }
    if(a[n].pos<r&&!a[n].flag) res+=r-a[n].pos;
    cout<<res+tot_s<<endl;
    return 0;
}

***室

时间限制: 1 Sec 内存限制: 128 MB
[提交] [状态]
题目描述
Bemy和Fife是两位大名鼎鼎的学(ji)佛(lao),他们为了蒸发学水,在课后仍然会缠着老师问问题。
在一次分班上课后,这两位学佛与老师讨论着高深的问题,不知不觉忘了时间。直到上课铃响了,他们才想起要回班级。在回班级时,他们会一路损失佛光。为了在回到班级时,有足够多的佛光蒸发学水,而使学水不被其他大佬蒸发,他们希望到两人回到班级时损失的总佛光最少。
Bemy和Fife所在的学校有N个教室,M条过道。Bemy一开始在1号教室,Fife在2号。他们的班级在n号教室。每当Bemy去往一个教室时,他会损失B点佛光;每当Fife去往一个教室时,他会损失F点佛光,值得注意的是,当Bemy和Fife一起行动时,他们会相互合作(py),使每次损失的佛光减少为P。

输入
第一行输入包含正整数B,F,P,N,M并且N最多是40,000。N,M,B,F和P如上所述,其中N>=3)。
输入中的下一个M行两个整数a,b表示教室a,b之间有走道。连接是双向的。

输出
一个整数,指定Bemy和Fife集体到达班级需要损失的最小佛光。
样例输入 Copy
4 4 5 8 8
1 4
2 3
3 4
4 7
2 5
5 6
6 8
7 8
样例输出 Copy
22
提示
样例解释:在例子中这里显示,Bemy从1到4,Fife从2到3,再从3到4,然后他们一起走从4到7到8。

题意:

B的起点是1,花费是b;F的起点是2,花费是 f;一起走的花费是 p ;问走到n的最小花费。

思路:

建图最短路很容易想到,但是难点在于汇合点在哪个地方。
因为无法确定汇合点的位置,可以直接遍历所有点,假设这个点是汇合点,求出花费,取min即是答案。
这时候B和F的最小花费都很好求,求一遍最短路即可。
想要知道一起走的花费,就需要知道一起走的路程,那么我们可以直接从终点跑一遍最短路,dis[i]就表示从终点到i点的最短路,这时候的花费也一定是最小花费。

因为n只有40000,所以求最短路可以用Dijkstra或spfa 。
注意是无向图

#include<bits/stdc++.h>
typedef long long ll;
using namespace std;
typedef pair<int,int>PII;
inline int read()
{
    int x=0,f=1;char s=getchar();
    while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
    while(s<='9'&&s>='0'){x=x*10+s-'0';s=getchar();}
    return x*f;
}
const int maxn=40010,maxm=maxn*2;
 
int h[maxn],e[maxm],ne[maxm],idx;
int dist1[maxn],dist2[maxn],dist[maxn];
bool st1[maxn],st2[maxn],st[maxn];
int b,f,p,n,m;
 
void add(int a,int b){
    e[idx]=b,ne[idx]=h[a],h[a]=idx++;
}
 
void dijkstra(int s,int *dis){
    memset(st,0,sizeof st);
    for(int i=1;i<=n;i++)
        dis[i]=0x3f3f3f3f;
    priority_queue<PII,vector<PII>,greater<PII>>heap;
    dis[s]=0;
    heap.push({0,s});
    while(heap.size()){
        auto t=heap.top();
        heap.pop();
        int ver=t.second,d=t.first;
        if(st[ver]) continue;///该点更新
        st[ver]=true;
        for(int i=h[ver];i!=-1;i=ne[i]){
            int j=e[i];
            if(dis[j]>d+1){
                dis[j]=d+1;
                heap.push({dis[j],j});
            }
        }
    }
}
int main(){
    b=read();f=read();p=read();n=read();m=read();
    memset(h,-1,sizeof h);
    while(m--){
        int u,v;
        u=read();v=read();
        add(u,v);
        add(v,u);
    }
    dijkstra(1,dist1);
    dijkstra(2,dist2);
    dijkstra(n,dist);
    int minn=0x3f3f3f3f;
    for(int i=1;i<=n;i++)
        minn=min(minn,b*dist1[i]+f*dist2[i]+p*dist[i]);
    cout<<minn<<endl;
    return 0;
}

自己被自己的sb想法卡了一晚上