20190825

期望: 60 + 30 + 20 = 110.实际: 40 + 0 + 10 = 50.

T1:给定一个正整数 M ,找出有多少不同的正整数对 (x, y) 使得存在正整数 p 和 q,满足下面这个方程:p*x2 + q*y = M.

S1:开局以为是数学题,套某个定理,想不到打了暴力,不知到>500的点为什么错了.后面跟dalao讨论,发现枚举的顺序有问题,导致TLE与WA.对于60pts,正确的打开方式应该为先枚举x( x<=sqrt ( m ) ),再枚举y( y<=m ),再枚举p.(p*x*x<m),一旦枚举到p,使x,y成立,就break.看上去o(n^3),其实为o(能过60pts).正解其实为暴力的优化,我们将p放在第二维枚举,第三维不枚举j,直接枚举m-x*x*p的因子,合法的y一定在其中,这样o(能过100pts)就解决了.

#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
using namespace std;
#define re register
int T,m,ans,vis[200010];
vector<int> v[200010];
inline int fd(){
    int s=1,t=0;
    char c=getchar();
    while(c<'0'||c>'9'){
        if(c=='-')
            s=-1;
        c=getchar();
    }
    while(c>='0'&&c<='9'){
        t=t*10+c-'0';
        c=getchar();
    }
    return s*t;
}
void work()
{
    for(re int i=1;i<=200000;++i)
        for(re int j=1;j*i<=200000;++j)
            v[i*j].push_back(i);
}
int main()
{
    freopen("pairs.in","r",stdin);
    freopen("pairs.out","w",stdout);
    T=fd(),work();
    while(T--){
        m=fd();
        ans=0;
        for(re int x=1;x*x<=m;++x){
            for(re int p=1;p*x*x<m;++p){
                int cnt=v[m-x*x*p].size();
                for(re int k=0;k<cnt;++k)
                    if(!vis[v[m-x*x*p][k]]){
                        ++ans;
                        vis[v[m-x*x*p][k]]=1;
                    }
            }
            for(re int p=1;p*x*x<m;++p){
                int cnt=v[m-x*x*p].size();
                for(re int k=0;k<cnt;++k)
                    vis[v[m-x*x*p][k]]=0;
            }
        }
        printf("%d\n",ans);
    }
    return 0;
}

T2:幼儿园老师正在给小朋友们排座位.一共有 N 个小朋友, M 个座位.为了尽量让小朋友分到自己喜欢的座位上去,决定让每个小朋友都选出两个自己最想坐的位置.小朋友们选好之后,老师却犯愁了.老师现在想知道,一共有多少种安排座位的方式能满足所有小朋友的意愿?由于答案可能很大,你需要将其对 10000019 取模后输出.

S2:显然30pts用于dfs,但是题目说明了小朋友选的两个座位可能是一样的,选择这两个座位的方案只算一种,在dfs要判重(30pts - > 0 pts).正解:考虑将座位看成点,小朋友喜欢的两个座位连一条双向边.我们要做的是将边定向.规定a-->b为选b,b-->a为选a.在一个n个点,m条边的联通块内,考虑以下几种情况:①:n<m,座位小于人数,显然无解.②:n-1==m.将每一个点做为根,都会使每一条边得到唯一方向,所以有n种方案.③:n==m,无自环.显然顺逆时针,两种方案.④:n==m,有自环,自环的两点选择唯一确定,全局方案唯一.最后利用乘法原理,将每个连通块的方案相乘即为ans.

#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
#define re register
const int mod=10000019;
const int maxn=200010*10+10;
int T,n,m,cnt,ans,vis[maxn],sum[maxn],head[maxn];
struct bian{
    int next,to;
}len[maxn<<1];
inline int fd(){
    int s=1,t=0;
    char c=getchar();
    while(c<'0'||c>'9'){
        if(c=='-')
            s=-1;
        c=getchar();
    }
    while(c>='0'&&c<='9'){
        t=t*10+c-'0';
        c=getchar();
    }
    return s*t;
}
void add(int from,int to){
    len[++cnt].to=to;
    len[cnt].next=head[from];
    head[from]=cnt;
}
void dfs(int x,int &n,int &m,int &flag){
    if(vis[x]) return;
    vis[x]=1;
    ++n,m+=sum[x];
    for(re int k=head[x];k;k=len[k].next){
        int to=len[k].to;
        if(to==x) flag=1;
        dfs(to,n,m,flag);
    }
}
int work(int x){
    int n=0,m=0,flag=0;
    dfs(x,n,m,flag);
    m/=2;
    if(m>n) return 0;
    if(flag) return 1;
    if(n==m) return 2;
    return n; 
}
int main()
{
    freopen("seat.in","r",stdin);
    freopen("seat.out","w",stdout);
    T=fd();
    while(T--){
        n=fd(),m=fd();
        memset(head,0,sizeof(head));
        memset(vis,0,sizeof(vis));
        memset(sum,0,sizeof(sum));
        for(re int i=1;i<=n;++i){
            int from=fd(),to=fd();
            add(from,to),add(to,from);
            ++sum[from],++sum[to];
        }
        ans=1;
        for(re int i=1;i<=m;++i)
            if(!vis[i])
                ans=1ll*ans*work(i)%mod;
        printf("%d\n",ans);
    }
    return 0;
}

T3:给定一个整数 N ,请你计算 (7 +4√3 ) N 的整数部分模 1000000007 后的结果.

 

#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
#define e exit(0)
#define re register
const int mod=1000000007;
int T,n,ans;
inline int fd(){
    int s=1,t=0;
    char c=getchar();
    while(c<'0'||c>'9'){
        if(c=='-')
            s=-1;
        c=getchar();
    }
    while(c>='0'&&c<='9'){
        t=t*10+c-'0';
        c=getchar();
    }
    return s*t;
}
struct jz{
    int a[5][5];
    jz(){memset(a,0,sizeof(a));}
    jz operator*(const jz &p){
        jz ans;
        for(re int k=1;k<=2;++k)
            for(re int i=1;i<=2;++i)
                for(re int j=1;j<=2;++j)
                    ans.a[i][j]=(ans.a[i][j]%mod+1ll*a[i][k]*p.a[k][j]%mod)%mod;
        return ans;
    }
};
jz work(){
    jz g;
    g.a[1][1]=7,g.a[1][2]=4;
    g.a[2][1]=12,g.a[2][2]=7;
    return g;
}
jz qsm(jz k,int y){
    jz ans;
    for(re int i=1;i<=2;++i)
        ans.a[i][i]=1;
    while(y){
        if(y&1) ans=ans*k;
        k=k*k;
        y>>=1;
    }
    return ans;
}
int main()
{
    freopen("math.in","r",stdin);
    freopen("math.out","w",stdout);
    T=fd();
    while(T--){    
        n=fd();
        if(n==0){
            printf("1\n");
            continue;
        }
        else if(n==1){
            printf("13\n");
            continue;
        }
        jz k=work();
        k=qsm(k,n-1);
        ans=(1ll*7*k.a[1][1]%mod+1ll*4*k.a[2][1]%mod)%mod;
        ans=(1ll*2*ans%mod-1%mod)%mod;
        printf("%d\n",ans);
    }
    return 0;
}

 

posted @ 2019-08-26 09:43  xqyxqy  阅读(122)  评论(0编辑  收藏  举报