2017福建省赛 FZU2272~2283

1.FZU2272 Frog

传送门:http://acm.fzu.edu.cn/problem.php?pid=2272

题意:鸡兔同笼通解

题解:解一个方程组直接输出就行

代码如下:

#include <map>
#include <set>
#include <cmath>
#include <ctime>
#include <stack>
#include <queue>
#include <cstdio>
#include <cctype>
#include <bitset>
#include <string>
#include <vector>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <functional>
#define fuck(x) cout<<"["<<x<<"]";
#define FIN freopen("input.txt","r",stdin);
#define FOUT freopen("output.txt","w+",stdout);
//#pragma comment(linker, "/STACK:102400000,102400000")
using namespace std;
typedef long long LL;
typedef pair<int, int> PII;
const int maxn = 1e5+5;
const int INF = 0x3f3f3f3f;
const int MOD = 1e9+7;


int main(){
#ifndef ONLINE_JUDGE
    FIN
#endif
    int T;
    scanf("%d",&T);
    while(T--){
        int n,m;
        cin>>n>>m;
        cout<<m/2-n<<" "<<2*n-m/2<<endl;
    }
}
View Code

2.FZU2273

传送门:http://acm.fzu.edu.cn/problem.php?pid=2273

题意:给你两个三角形,让你判断三角形是相交,相离,还是包含

题解:计算几何模板题,先判断三角形A有没有点在三角形B里面,三角形B有没有点在三角形A里面,然后分情况讨论即可

代码如下:

#include<iostream>
#include<cmath>
using namespace std;
struct point{
    int x,y;
}s[5][5];

double m(point a,point b,point c)            //叉积 
{
    return ((b.x-a.x)*(c.y-a.y)-(b.y-a.y)*(c.x-a.x));
}

bool Judge(point u1,point u2,point v1,point v2)        //判断两条线段相交情况 
{
   return (max(u1.x,u2.x)>=min(v1.x,v2.x)&&
           max(u1.y,u2.y)>=min(v1.y,v2.y)&&
           max(v1.x,v2.x)>=min(u1.x,u2.x)&&
           max(v1.y,v2.y)>=min(u1.y,u2.y)&&
           m(u1,v1,u2)*m(u1,u2,v2)>=0&&
           m(v1,u1,v2)*m(v1,v2,u2)>=0);
}

int line_check(int p,int q)                     //判断两个三角形是否相交 
{
    return (Judge(s[p][0],s[p][1],s[q][0],s[q][1])||
           Judge(s[p][0],s[p][1],s[q][1],s[q][2])||
           Judge(s[p][0],s[p][1],s[q][0],s[q][2])||
           Judge(s[p][1],s[p][2],s[q][0],s[q][1])||
           Judge(s[p][1],s[p][2],s[q][1],s[q][2])||
           Judge(s[p][1],s[p][2],s[q][0],s[q][2])||
           Judge(s[p][0],s[p][2],s[q][0],s[q][1])||
           Judge(s[p][0],s[p][2],s[q][1],s[q][2])||
           Judge(s[p][0],s[p][2],s[q][0],s[q][2]));
} 

int point_check(int p,int q)        // 面积法判断点在三角形内
{
    double res=fabs(m(s[q][0],s[q][1],s[q][2])); 
    int ans=0;
    for(int i=0;i<3;i++)
    {
        double res1=fabs(m(s[q][0],s[q][1],s[p][i]));
        double res2=fabs(m(s[q][1],s[q][2],s[p][i]));
        double res3=fabs(m(s[q][0],s[q][2],s[p][i]));
        if(res1+res2+res3==res)
          ans++;
    }
    return ans;
}

int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        for(int i=0;i<2;i++)
          for(int j=0;j<3;j++)
            cin>>s[i][j].x>>s[i][j].y;
        int ans1=point_check(0,1),ans2=point_check(1,0);
        if(ans1==0&&ans2==0)                     //如果两个三角形没有一个点在另一个三角形内 
        {
            int ans=line_check(0,1);
            if(ans==0)
              cout<<"disjoint"<<endl;       // 相离
            else
               cout<<"intersect"<<endl;        //相交
        }         
        else if(ans1==3||ans2==3)
          cout<<"contain"<<endl;                //否则包含 
        else 
          cout<<"intersect"<<endl;        //相交 
    }
    return 0;
}
View Code

3.FZU2275

传送门:http://acm.fzu.edu.cn/problem.php?pid=2275

题意:Alice有数字A,Bob有数字B,他们两个人可以对数字进行 1.删除最后一个数,2.将整个数字反转这两个操作,Alice想要将她的数字变得和Bob一样,Bob不想Alice的数字变得和她的一样,最后如果Alice变得和Bob一样了,则Alice赢,否则Bob赢,问你谁会赢

题解:1.如果Bob长度比Alice的数字长度长的话,Bob只需要不断反转他的数字即可,Alice不可能赢

   2.如果Bob的数字为0的话,Alice一定赢

   3.如果Bob的数字是Alice的数字的子串或者Bob数字的反转是Alice数字的子串的话,那么Alice一定赢

代码如下:

#include <map>
#include <set>
#include <cmath>
#include <ctime>
#include <stack>
#include <queue>
#include <cstdio>
#include <cctype>
#include <bitset>
#include <string>
#include <vector>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <functional>
#define fuck(x) cout<<"["<<x<<"]";
#define FIN freopen("input.txt","r",stdin);
#define FOUT freopen("output.txt","w+",stdout);
//#pragma comment(linker, "/STACK:102400000,102400000")
using namespace std;
typedef long long LL;
typedef pair<int, int> PII;
const int maxn = 1e5+5;
const int INF = 0x3f3f3f3f;
const int MOD = 1e9+7;
int Nxt[maxn];
void makeNext(char P[]) {
    int m = strlen(P);
    Nxt[0] = 0;
    for (int q = 1, k = 0; q < m; ++q) {
        while (k > 0 && P[q] != P[k]) k = Nxt[k - 1];
        if (P[q] == P[k]) k++;
        Nxt[q] = k;
    }
}
int kmp(char T[], char P[]) {
    int n = strlen(T), m = strlen(P);
    makeNext(P);
    for (int i = 0, q = 0; i < n; ++i) {
        while (q > 0 && P[q] != T[i]) q = Nxt[q - 1];
        if (P[q] == T[i]) q++;
        if (q == m) return i - m + 1;   //Æ¥Åä³É¹¦,·µ»Ø³É¹¦Ê±Ê×λÖÃ
    }
    return -1;//Æ¥Åäʧ°Ü
}

int main(){
#ifndef ONLINE_JUDGE
    FIN
#endif
    char str1[maxn];
    char str2[maxn];
    char str3[maxn];
    int T;
    scanf("%d",&T);
    while(T--){
        cin>>str1>>str2;
        int len1=strlen(str1);
        int len2=strlen(str2);
        for(int i=0;i<len2;i++){
            str3[len2-i-1]=str2[i];
        }
        if(len2==1&&str2[0]=='0'){
            cout<<"Alice"<<endl;
            continue;
        }
        str3[len2]='';
        if(len1<len2){
            cout<<"Bob"<<endl;
        }else{
            int ans1=kmp(str1,str2);
            int ans2=kmp(str1,str3);
            if(ans1!=-1||ans2!=-1){
                cout<<"Alice"<<endl;
            }else cout<<"Bob"<<endl;
        }
    }
}
View Code

4.FZU2277

传送门:http://acm.fzu.edu.cn/problem.php?pid=2277

题意:给你一颗树的结构,有两种操作,1.将给定节点和这个节点的所有子树上的权值 value += x-deep*k ,2.询问这个节点的权值

题解:线段树和的dfs序,线段树维护该区间节点的权值,dfs序修改其子树的权值,具体题解看代码注释

代码如下:

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define fuck(x) cout<<"["<<x<<"]";
#define FIN freopen("input.txt","r",stdin);
#define FOUT freopen("output.txt","w+",stdout);
#define lson root<<1
#define rson root<<1|1
#pragma comment(linker, "/STACK:102400000,102400000")
using namespace std;
typedef long long LL;
typedef pair<int, int> PII;
const int maxn = 8e5+7;
const int INF = 0x3f3f3f3f;
const int mod = 1e9+7;
int n,q;
struct node{
    int l,r;
    LL sum1;//sum1记录需要加上来的数
    LL sum2;//sum2记录需要减去的数
}Tree[maxn<<2];
int ltid[maxn]; //更新的左区间
int rtid[maxn]; //更新的右区间
int dep[maxn]; //维护每个节点的深度
struct E{
    int v,next;
}edge[maxn];
int head[maxn];
int tot,top;
//前向星建图
inline void add(int u,int v){
    edge[tot].v=v;
    edge[tot].next=head[u];
    head[u]=tot++;
}
//dfs序查询子树的点权和
void dfs(int u,int deep){
    ltid[u]=++top;
    dep[u]=deep;
    for(int i=head[u];i!=-1;i=edge[i].next){
        int v=edge[i].v;
        dfs(v,deep+1);
    }
    rtid[u]=top;
    //这样从左到右的一段区间了【lrid,rtid】就表示了节点u的子树权值
    return;
}
//建树,节点value值初始化为0
void build(int l,int r ,int root){
    Tree[root].l=l;
    Tree[root].r=r;
    Tree[root].sum1=Tree[root].sum2=0;
    if(l==r) return;
    int mid=(l+r)>>1;
    build(l,mid,lson);
    build(mid+1,r,rson);
}
void Add(LL &a,LL b){
    a+=b;
    a%=mod;
}
//更新节点和子树的sum1和sum2
void push_down(int root){
    LL a=Tree[root].sum1;
    LL b=Tree[root].sum2;
    if(a) Add(Tree[lson].sum1,a);
    if(a) Add(Tree[rson].sum1,a);
    if(b) Add(Tree[lson].sum2,b);
    if(b) Add(Tree[rson].sum2,b);
    Tree[root].sum1=Tree[root].sum2=0;
}

void update(int L,int R,LL x,LL k,int root){
    int l=Tree[root].l;
    int r=Tree[root].r;
    int mid=(l+r)/2;
    if(L<=l&&r<=R){
        //到了需要更改的区间
        Add(Tree[root].sum1,x);  //sum1加上x
        Add(Tree[root].sum2,k);  //sum2加上k   
        return;
    }
    //更新树
    push_down(root);
    //更新区间
    if(L>mid) update(L,R,x,k,rson);
    else if(R<=mid) update(L,R,x,k,lson);
    else {
        update(L,mid,x,k,lson);
        update(mid+1,R,x,k,rson);
    }
}
LL query(int p,int deep,int root){
    if(Tree[root].l==Tree[root].r){
        //查询值为  ai+=x-k*deep
        return ((Tree[root].sum1-Tree[root].sum2*deep%mod)+mod)%mod;
    }
    push_down(root);
    int mid=(Tree[root].l+Tree[root].r)/2;
    if(p<=mid) return query(p,deep,lson);
    return query(p,deep,rson);
}
int main(){
    int T;
    scanf("%d",&T);
    while(T--){
        scanf("%d",&n);
        memset(head,-1,sizeof(head));
        tot=0;top=0;
        int u;
        for(int i=2;i<=n;i++){
            scanf("%d",&u);
            add(u,i);
        }
        dfs(1,1);
        build(1,n,1);
        int op,v,x,k;
        scanf("%d",&q);
        while(q--){
            scanf("%d",&op);
            if(op==1){
                scanf("%d%d%d",&v,&x,&k);   
                //注意 因为会出现负数,所以我们每次减的操作变成+,最后查询的时候再减
                //用两个值分别存所需要加的数和所需要减的数,最后查询的时候操作即可
                update(ltid[v],rtid[v],(x*1LL+dep[v]*1LL*k%mod)%mod,k,1);
            }else{
                scanf("%d",&v);
                //查询时用
                printf("%lld
",query(ltid[v],dep[v],1));
            }
        }
    }
    return 0;
}
View Code

5.FZU2278

传送门:http://acm.fzu.edu.cn/problem.php?pid=2278

题意:有n张牌需要你去抽,每次抽牌的概率是一样的,你每过(n-1)!天可以抽一张牌,求抽齐所有牌的数学期望值

题解:如果我有a张卡,那么我抽到第a+1张卡的概率是(n-a)/n,那么我抽到第a+1张卡平均就需要n/(n-a)天,每隔(n-1)!天就可以抽一次牌

那么我们最后推出来公式就是(n-1)!*n(1+1/2+1/3+……1/n),因为数字特别大,我们要用到大数的知识

三种写法:

1.c++的大数模板

2.Java 的Bignumber

3.python直接写 果然py是最强的

代码如下:

#include <map>
#include <set>
#include <cmath>
#include <ctime>
#include <stack>
#include <queue>
#include <cstdio>
#include <cctype>
#include <bitset>
#include <string>
#include <vector>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <functional>
using namespace std; 

#define MAXN 9999
#define MAXSIZE 10
#define DLEN 4

class BigNum
{ 
private: 
    int a[20005];    //可以控制大数的位数 
    int len;       //大数长度
public: 
    BigNum(){ len = 1;memset(a,0,sizeof(a)); }   //构造函数
    BigNum(const int);       //将一个int类型的变量转化为大数
    BigNum(const char*);     //将一个字符串类型的变量转化为大数
    BigNum(const BigNum &);  //拷贝构造函数
    BigNum &operator=(const BigNum &);   //重载赋值运算符,大数之间进行赋值运算

    friend istream& operator>>(istream&,  BigNum&);   //重载输入运算符
    friend ostream& operator<<(ostream&,  BigNum&);   //重载输出运算符

    BigNum operator+(const BigNum &) const;   //重载加法运算符,两个大数之间的相加运算 
    BigNum operator-(const BigNum &) const;   //重载减法运算符,两个大数之间的相减运算 
    BigNum operator*(const BigNum &) const;   //重载乘法运算符,两个大数之间的相乘运算 
    BigNum operator/(const int   &) const;    //重载除法运算符,大数对一个整数进行相除运算

    BigNum operator^(const int  &) const;    //大数的n次方运算
    int    operator%(const int  &) const;    //大数对一个int类型的变量进行取模运算    
    bool   operator>(const BigNum & T)const;   //大数和另一个大数的大小比较
    bool   operator>(const int & t)const;      //大数和一个int类型的变量的大小比较

    void print();       //输出大数
}; 
BigNum::BigNum(const int b)     //将一个int类型的变量转化为大数
{ 
    int c,d = b;
    len = 0;
    memset(a,0,sizeof(a));
    while(d > MAXN)
    {
        c = d - (d / (MAXN + 1)) * (MAXN + 1); 
        d = d / (MAXN + 1);
        a[len++] = c;
    }
    a[len++] = d;
}
BigNum::BigNum(const char*s)     //将一个字符串类型的变量转化为大数
{
    int t,k,index,l,i;
    memset(a,0,sizeof(a));
    l=strlen(s);   
    len=l/DLEN;
    if(l%DLEN)
        len++;
    index=0;
    for(i=l-1;i>=0;i-=DLEN)
    {
        t=0;
        k=i-DLEN+1;
        if(k<0)
            k=0;
        for(int j=k;j<=i;j++)
            t=t*10+s[j]-'0';
        a[index++]=t;
    }
}
BigNum::BigNum(const BigNum & T) : len(T.len)  //拷贝构造函数
{ 
    int i; 
    memset(a,0,sizeof(a)); 
    for(i = 0 ; i < len ; i++)
        a[i] = T.a[i]; 
} 
BigNum & BigNum::operator=(const BigNum & n)   //重载赋值运算符,大数之间进行赋值运算
{
    int i;
    len = n.len;
    memset(a,0,sizeof(a)); 
    for(i = 0 ; i < len ; i++) 
        a[i] = n.a[i]; 
    return *this; 
}
istream& operator>>(istream & in,  BigNum & b)   //重载输入运算符
{
    char ch[MAXSIZE*4];
    int i = -1;
    in>>ch;
    int l=strlen(ch);
    int count=0,sum=0;
    for(i=l-1;i>=0;)
    {
        sum = 0;
        int t=1;
        for(int j=0;j<4&&i>=0;j++,i--,t*=10)
        {
            sum+=(ch[i]-'0')*t;
        }
        b.a[count]=sum;
        count++;
    }
    b.len =count++;
    return in;

}
ostream& operator<<(ostream& out,  BigNum& b)   //重载输出运算符
{
    int i;  
    cout << b.a[b.len - 1]; 
    for(i = b.len - 2 ; i >= 0 ; i--)
    { 
        cout.width(DLEN); 
        cout.fill('0'); 
        cout << b.a[i]; 
    } 
    return out;
}

BigNum BigNum::operator+(const BigNum & T) const   //两个大数之间的相加运算
{
    BigNum t(*this);
    int i,big;      //位数   
    big = T.len > len ? T.len : len; 
    for(i = 0 ; i < big ; i++) 
    { 
        t.a[i] +=T.a[i]; 
        if(t.a[i] > MAXN) 
        { 
            t.a[i + 1]++; 
            t.a[i] -=MAXN+1; 
        } 
    } 
    if(t.a[big] != 0)
        t.len = big + 1; 
    else
        t.len = big;   
    return t;
}
BigNum BigNum::operator-(const BigNum & T) const   //两个大数之间的相减运算 
{  
    int i,j,big;
    bool flag;
    BigNum t1,t2;
    if(*this>T)
    {
        t1=*this;
        t2=T;
        flag=0;
    }
    else
    {
        t1=T;
        t2=*this;
        flag=1;
    }
    big=t1.len;
    for(i = 0 ; i < big ; i++)
    {
        if(t1.a[i] < t2.a[i])
        { 
            j = i + 1; 
            while(t1.a[j] == 0)
                j++; 
            t1.a[j--]--; 
            while(j > i)
                t1.a[j--] += MAXN;
            t1.a[i] += MAXN + 1 - t2.a[i]; 
        } 
        else
            t1.a[i] -= t2.a[i];
    }
    t1.len = big;
    while(t1.a[len - 1] == 0 && t1.len > 1)
    {
        t1.len--; 
        big--;
    }
    if(flag)
        t1.a[big-1]=0-t1.a[big-1];
    return t1; 
} 

BigNum BigNum::operator*(const BigNum & T) const   //两个大数之间的相乘运算 
{ 
    BigNum ret; 
    int i,j,up; 
    int temp,temp1;   
    for(i = 0 ; i < len ; i++)
    { 
        up = 0; 
        for(j = 0 ; j < T.len ; j++)
        { 
            temp = a[i] * T.a[j] + ret.a[i + j] + up; 
            if(temp > MAXN)
            { 
                temp1 = temp - temp / (MAXN + 1) * (MAXN + 1); 
                up = temp / (MAXN + 1); 
                ret.a[i + j] = temp1; 
            } 
            else
            { 
                up = 0; 
                ret.a[i + j] = temp; 
            } 
        } 
        if(up != 0) 
            ret.a[i + j] = up; 
    } 
    ret.len = i + j; 
    while(ret.a[ret.len - 1] == 0 && ret.len > 1)
        ret.len--; 
    return ret; 
} 
BigNum BigNum::operator/(const int & b) const   //大数对一个整数进行相除运算
{ 
    BigNum ret; 
    int i,down = 0;   
    for(i = len - 1 ; i >= 0 ; i--)
    { 
        ret.a[i] = (a[i] + down * (MAXN + 1)) / b; 
        down = a[i] + down * (MAXN + 1) - ret.a[i] * b; 
    } 
    ret.len = len; 
    while(ret.a[ret.len - 1] == 0 && ret.len > 1)
        ret.len--; 
    return ret; 
}
int BigNum::operator %(const int & b) const    //大数对一个int类型的变量进行取模运算    
{
    int i,d=0;
    for (i = len-1; i>=0; i--)
    {
        d = ((d * (MAXN+1))% b + a[i])% b;  
    }
    return d;
}
BigNum BigNum::operator^(const int & n) const    //大数的n次方运算
{
    BigNum t,ret(1);
    int i;
    if(n<0)
        exit(-1);
    if(n==0)
        return 1;
    if(n==1)
        return *this;
    int m=n;
    while(m>1)
    {
        t=*this;
        for( i=1;i<<1<=m;i<<=1)
        {
            t=t*t;
        }
        m-=i;
        ret=ret*t;
        if(m==1)
            ret=ret*(*this);
    }
    return ret;
}
bool BigNum::operator>(const BigNum & T) const   //大数和另一个大数的大小比较
{ 
    int ln; 
    if(len > T.len)
        return true; 
    else if(len == T.len)
    { 
        ln = len - 1; 
        while(a[ln] == T.a[ln] && ln >= 0)
            ln--; 
        if(ln >= 0 && a[ln] > T.a[ln])
            return true; 
        else
            return false; 
    } 
    else
        return false; 
}
bool BigNum::operator >(const int & t) const    //大数和一个int类型的变量的大小比较
{
    BigNum b(t);
    return *this>b;
}

void BigNum::print()    //输出大数
{ 
    int i;   
    cout << a[len - 1]; 
    for(i = len - 2 ; i >= 0 ; i--)
    { 
        cout.width(DLEN); 
        cout.fill('0'); 
        cout << a[i]; 
    } 
}
int main(void)
{
    int i,n;
    int T;
    cin>>T;
    while(T--){
            BigNum x;      //定义大数的对象数组
            BigNum ans;
            int n;
            cin>>n;
            x=1;
            for(int i=1;i<=n;i++){
                x=x*i;
            }
            for(int i=1;i<=n;i++){
                ans=ans+(x/i);
            }
            ans.print();
            cout<<".0"<<endl;
        }
    }
View Code
import java.util.*;
import java.math.*;
public class Main {
    public static void main(String[] args) {
      int t;
      Scanner sc=new Scanner(System.in);
      t=sc.nextInt();
      for(int cc=0;cc<t;cc++)
      {
          BigInteger b=BigInteger.valueOf(1);
          int n;
          n=sc.nextInt();
          for(int i=1;i<=n;i++)
          {
             b=b.multiply(BigInteger.valueOf(i));
          }
          BigInteger d=BigInteger.valueOf(0);
          for(int i=1;i<=n;i++)
          {
              BigInteger mm=b.divide(BigInteger.valueOf(i));
             d=d.add(mm);
          }
          System.out.println(d+".0");
      }
    }
}
View Code

6.FZU2281

传送门:http://acm.fzu.edu.cn/problem.php?pid=2281

题意:你手上有m元,可以买和卖货物,货物在n天的价格各不相同,求你n天过后最多可以有多少钱

题解:将货物的价格画成一个曲线,那么我们就可以发现,我们需要在货物价格低的时候买,价格高的时候卖,因为有多个波谷和波峰,就需要对每一个波谷和波峰进行买和卖的操作,这题也是大数,需要用到大数模板

代码如下:

#include <map>
#include <set>
#include <cmath>
#include <ctime>
#include <stack>
#include <queue>
#include <cstdio>
#include <cctype>
#include <bitset>
#include <string>
#include <vector>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <functional>
#define fuck(x) cout<<"["<<x<<"]";
#define FIN freopen("input.txt","r",stdin);
#define FOUT freopen("output.txt","w+",stdout);
//#pragma comment(linker, "/STACK:102400000,102400000")
using namespace std;
typedef long long LL;
typedef pair<int, int> PII;
const int maxn = 3e3+5;
const int INF = 0x3f3f3f3f;
const int mod = 1e9+7;

const int MAXL = 6e3+5;
const int MAXN = 9999;
const int DLEN = 4;
class Big {
public:
    int a[MAXL], len;
    Big(const int b = 0) {
        int c, d = b;
        len = 0;
        memset(a, 0, sizeof(a));
        while(d > MAXN) {
            c = d - (d / (MAXN + 1)) * (MAXN + 1);
            d = d / (MAXN + 1);
            a[len++] = c;
        }
        a[len++] = d;
    }
    Big(const char *s) {
        int t, k, index, L;
        memset(a, 0, sizeof(a));
        L = strlen(s);
        len = L / DLEN;
        if(L % DLEN) len++;
        index = 0;
        for(int i = L - 1; i >= 0; i -= DLEN) {
            t = 0;
            k = i - DLEN + 1;
            if(k < 0) k = 0;
            for(int j = k; j <= i; j++) t = t * 10 + s[j] - '0';
            a[index++] = t;
        }
    }
    Big operator/(const LL &b)const {
        Big ret;
        LL down = 0;
        for(int i = len - 1; i >= 0; i--) {
            ret.a[i] = (a[i] + down * (MAXN + 1)) / b;
            down = a[i] + down * (MAXN + 1) - ret.a[i] * b;
        }
        ret.len = len;
        while(ret.a[ret.len - 1] == 0 && ret.len > 1) ret.len--;
        return ret;
    }
    bool operator>(const Big &T)const {
        int ln;
        if(len > T.len) return true;
        else if(len == T.len) {
            ln = len - 1;
            while(a[ln] == T.a[ln] && ln >= 0) ln--;
            if(ln >= 0 && a[ln] > T.a[ln]) return true;
            else return false;
        } else return false;
    }
    Big operator+(const Big &T)const {
        Big t(*this);
        int big = T.len > len ? T.len : len;
        for(int i = 0; i < big; i++) {
            t.a[i] += T.a[i];
            if(t.a[i] > MAXN) {
                t.a[i + 1]++;
                t.a[i] -= MAXN + 1;
            }
        }
        if(t.a[big] != 0) t.len = big + 1;
        else t.len = big;
        return t;
    }
    Big operator-(const Big &T)const {
        int big;
        bool flag;
        Big t1, t2;
        if(*this > T) {
            t1 = *this;
            t2 = T;
            flag = 0;
        } else {
            t1 = T; t2 = *this; flag = 1;
        }
        big = t1.len;
        for(int i = 0; i < big; i++) {
            if(t1.a[i] < t2.a[i]) {
                int j = i + 1;
                while(t1.a[j] == 0) j++;
                t1.a[j--]--;
                while(j > i) t1.a[j--] += MAXN;
                t1.a[i] += MAXN + 1 - t2.a[i];
            } else t1.a[i] -= t2.a[i];
        }
        t1.len = big;
        while(t1.a[t1.len - 1] == 0 && t1.len > 1) {
            t1.len--;
            big--;
        }
        if(flag) t1.a[big - 1] = 0 - t1.a[big - 1];
        return t1;
    }
    LL operator%(const int &b)const {
        LL d = 0;
        for(int i = len - 1; i >= 0; i--) d = ((d * (MAXN + 1)) % b + a[i]) % b;
        return d;
    }
    Big operator*(const Big &T) const {
        Big ret;
        int i, j, up, temp, temp1;
        for(i = 0; i < len; i++) {
            up = 0;
            for(j = 0; j < T.len; j++) {
                temp = a[i] * T.a[j] + ret.a[i + j] + up;
                if(temp > MAXN) {
                    temp1 = temp - temp / (MAXN + 1) * (MAXN + 1);
                    up = temp / (MAXN + 1);
                    ret.a[i + j] = temp1;
                } else {
                    up = 0;
                    ret.a[i + j] = temp;
                }
            }
            if(up != 0)  ret.a[i + j] = up;
        }
        ret.len = i + j;
        while(ret.a[ret.len - 1] == 0 && ret.len > 1) ret.len--;
        return ret;
    }
    void print() {
        printf("%d", a[len - 1]);
        for(int i = len - 2; i >= 0; i--) printf("%04d", a[i]);
    }
};
int a[maxn];
int main(){
    int T;
    int cas=1;
    scanf("%d",&T);
    while(T--){
        int n,m;
        printf("Case #%d: ",cas++);
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++){
            scanf("%d",&a[i]);
        }
        if(m==0){
            printf("0
");
            continue;
        }
        Big ans=m;
        int by=n;
        for(int i=1;i<n;i++){
            if(a[i+1]>a[i]){
                by=i;
                break;
            }
        }
        if(by<n){
            Big x=ans/a[by],y=ans%a[by];
            while(by<n){
                int sl=by+1;
                while(sl<n&&a[sl+1]>=a[sl]) sl++;
                if(sl==n){
                    ans=x*a[sl]+y;
                    break;
                }else{
                    ans=x*a[sl]+y;
                    by=sl+1;
                    while(by<n&&a[by]>=a[by+1]) by++;
                    if(by<n) x=ans/a[by],y=ans%a[by];
                }
            }
        }
        
        LL x=ans%mod;
        cout<<x<<endl;
    }
}
View Code

7.FZU2282

传送门:http://acm.fzu.edu.cn/problem.php?pid=2282

题意:有一个1~n的全排列,你需要对他进行操作,使得至少有k个人的位置在原来的位置,而剩下的人不在本身的位置

题解:错位排列,公式:

代码如下:

#include <map>
#include <set>
#include <cmath>
#include <ctime>
#include <stack>
#include <queue>
#include <cstdio>
#include <cctype>
#include <bitset>
#include <string>
#include <vector>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <functional>
#define fuck(x) cout<<"["<<x<<"]";
#define FIN freopen("input.txt","r",stdin);
#define FOUT freopen("output.txt","w+",stdout);
//#pragma comment(linker, "/STACK:102400000,102400000")
using namespace std;
typedef long long LL;
typedef pair<int, int> PII;
const int maxn = 1e5+5;
const int INF = 0x3f3f3f3f;
const int mod = 1e9+7;
LL Jc[maxn];
LL c[maxn];
void calJc()    //求maxn以内的数的阶乘
{
    Jc[0] = Jc[1] = 1;
    Jc[2]=2;
    c[0]=1;
    c[1]=0;
    c[2]=1;
    for(LL i = 3; i < maxn; i++){
        c[i]=(((i-1)%mod)*((c[i-1]+c[i-2])%mod))%mod;
        Jc[i] = Jc[i - 1] * i % mod;
    }
}
//费马小定理求逆元
LL pow(LL a, LL n, LL p)    //快速幂 a^n % p
{
    LL ans = 1;
    while(n)
    {
        if(n & 1) ans = ans * a % p;
        a = a * a % p;
        n >>= 1;
    }
    return ans;
}
LL niYuan(LL a, LL b)   //费马小定理求逆元
{
    return pow(a, b - 2, b);
}
LL C(LL a, LL b)    //计算C(a, b)
{
    return Jc[a] * niYuan(Jc[b], mod) % mod* niYuan(Jc[a - b], mod) % mod;
}
int main(){
    calJc();
    int T;
    scanf("%d",&T);
    while(T--){
        int n,k;
        scanf("%d%d",&n,&k);
        LL ans=0;
        for(int i=0;i<k;i++){
            ans=((ans%mod)+(C(n,i)*c[n-i])%mod)%mod;
        }
        printf("%lld
",(mod+Jc[n]%mod-ans%mod)%mod);
    }
}
View Code

8.FZU2283

传送门:http://acm.fzu.edu.cn/problem.php?pid=2283

题意:玩 x棋,Kim先手,给你当前场上的局势和Kim的棋子,每个人都走最优步,问谁可以赢

题解:玩过这个游戏的都知道,只要你场上还有足够的空间并且你占据了中心的那个格子,你是一定赢的,如果不知道为什么,多玩几把就行,所以我们只需要数场上的空格和判断中心即可

代码如下:

#include <map>
#include <set>
#include <cmath>
#include <ctime>
#include <stack>
#include <queue>
#include <cstdio>
#include <cctype>
#include <bitset>
#include <string>
#include <vector>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <functional>
#define fuck(x) cout<<"["<<x<<"]";
#define FIN freopen("input.txt","r",stdin);
#define FOUT freopen("output.txt","w+",stdout);
//#pragma comment(linker, "/STACK:102400000,102400000")
using namespace std;
typedef long long LL;
typedef pair<int, int> PII;
const int maxn = 1e5+5;
const int INF = 0x3f3f3f3f;
const int MOD = 1e9+7;
char mp[4][4];

int main(){
#ifndef ONLINE_JUDGE
    FIN
#endif
    int T;
    cin>>T;
    while(T--){
        char ch;
        int cnt=0;
        for(int i=0;i<3;i++){
            for(int j=0;j<3;j++){
                cin>>mp[i][j];
                if(mp[i][j]=='.') cnt++;
            }
        }
        cin>>ch;
        int flag;
        if(cnt<=5){
            if(mp[1][1]==ch||mp[1][1]=='.') flag=1;
            else flag=0;
        }else flag=0;
        if(flag) cout<<"Kim win!"<<endl;
        else cout<<"Cannot win!"<<endl;
    }
}
View Code

以后一定好好写线段树嘤嘤嘤

 

 

每一个不曾刷题的日子 都是对生命的辜负 从弱小到强大,需要一段时间的沉淀,就是现在了 ~buerdepepeqi
原文地址:https://www.cnblogs.com/buerdepepeqi/p/9512333.html