HDU 6395 分段矩阵快速幂 HDU 6386 建虚点+dij

http://acm.hdu.edu.cn/showproblem.php?pid=6395

 

Sequence

Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others)
Total Submission(s): 1475    Accepted Submission(s): 539


Problem Description
Let us define a sequence as below

F1F2Fn===ABCFn2+DFn1+Pn


  Your job is simple, for each task, you should output  Fn module  109+7.
 

 

Input
The first line has only one integer  T, indicates the number of tasks.

Then, for the next  T lines, each line consists of  6 integers,  A ,  BCDPn.

1T200A,B,C,D1091P,n109
 

 

Sample Input
2 3 3 2 1 3 5 3 2 2 2 1 4
 

 

Sample Output
36 24
 
解析  p/n 不是定值不能直接矩阵快速幂  但是观察发现
23 
 1     2   3   4   5   6   7   8   9  10  11  12  13...100   除数
 23  12  7   5   4   3   3   2    2   2   2   1    1 .... 0      商

    商的个数很少 我们可以 分段矩阵快速幂   怕超时 可以先打1e5的表    一开始以为要用逆元解决问题  真的智障了

#include <bits/stdc++.h>
#define mp make_pair
#define pb push_back
#define fi first
#define se second
#define all(a) (a).begin(), (a).end()
#define fillchar(a, x) memset(a, x, sizeof(a))
#define huan printf("\n");
#define debug(a,b) cout<<a<<" "<<b<<" "<<endl;
using namespace std;
typedef long long ll;
const ll maxn=3,inf=0x3f3f3f3f,mod=1e9+7;
bool Finish_read;
template<class T>inline void read(T &x)
{
    Finish_read=0;
    x=0;
    int f=1;
    char ch=getchar();
    while(!isdigit(ch))
    {
        if(ch=='-')f=-1;
        if(ch==EOF)return;
        ch=getchar();
    }
    while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
    x*=f;
    Finish_read=1;
}
template<class T>inline void print(T x)
{
    if(x/10!=0)print(x/10);
    putchar(x%10+'0');
}
template<class T>inline void writeln(T x)
{
    if(x<0)putchar('-');
    x=abs(x);
    print(x);
    putchar('\n');
}
template<class T>inline void write(T x)
{
    if(x<0)putchar('-');
    x=abs(x);
    print(x);
}
ll n,a,b,c,d,p;
struct Matrix
{
    ll m[maxn][maxn];
    Matrix()
    {
        memset(m,0,sizeof(m));
    }
    void init()
    {
        for(int i=0; i<maxn; i++)
            for(int j=0; j<maxn; j++)
                m[i][j]=(i==j);
    }
    Matrix  operator +(const Matrix &b)const
    {
        Matrix c;
        for(int i=0; i<maxn; i++)
        {
            for(int j=0; j<maxn; j++)
            {
                c.m[i][j]=(m[i][j]+b.m[i][j])%mod;
            }
        }
        return c;
    }
    Matrix  operator *(const Matrix &b)const
    {
        Matrix c;
        for(int i=0; i<maxn; i++)
        {
            for(int j=0; j<maxn; j++)
            {
                for(int k=0; k<maxn; k++)
                {
                    c.m[i][j]=(c.m[i][j]+(m[i][k]*b.m[k][j])%mod)%mod;
                }
            }
        }
        return c;
    }
    Matrix  operator^(const ll &t)const
    {
        Matrix ans,a=(*this);
        ans.init();
        ll n=t;
        while(n)
        {
            if(n&1) ans=ans*a;
            a=a*a;
            n>>=1;
        }
        return ans;
    }
};
ll f[100010];
pair<ll,ll> solve(ll x,ll y,ll z,ll m)
{
    Matrix a,b,temp;
    b.m[0][0]=d;b.m[0][1]=c;b.m[0][2]=1;
    b.m[1][0]=1;b.m[2][2]=1;
    a.m[0][0]=x;
    a.m[1][0]=y;
    a.m[2][0]=z;
    temp=b^(m);
    temp=temp*a;
    return mp(temp.m[0][0],temp.m[1][0]);
}
int main()
{
    int t;
    read(t);
    while(t--)
    {
        read(a);read(b);read(c);read(d);read(p);read(n);
        f[1]=a;f[2]=b;
        for(int i=3;i<=100000;i++)
            f[i]=(c*f[i-2]%mod+d*f[i-1]%mod+p/i)%mod;
        if(n<=100000)
            writeln(f[n]);
        else
        {
            ll l=100000;
            pair<ll,ll> pp(f[l],f[l-1]);l++;
            while(l<=n)
            {
                ll temp=p/l;
                if(temp==0)
                {
                    pp=solve(pp.fi,pp.se,temp,n-l+1);
                    writeln(pp.fi);
                    break;
                }
                ll temp2=p/temp;
                if(temp2>=n)
                {
                    pp=solve(pp.fi,pp.se,temp,n-l+1);
                    writeln(pp.fi);
                    break;
                }
                else
                {
                    pp=solve(pp.fi,pp.se,temp,temp2-l+1);
                    l=temp2+1;
                }
            }
        }
    }
}

 

http://acm.hdu.edu.cn/showproblem.php?pid=6386

Age of Moyu

Time Limit: 5000/2500 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others)
Total Submission(s): 2237    Accepted Submission(s): 683


Problem Description
Mr.Quin love fishes so much and Mr.Quin’s city has a nautical system,consisiting of  N ports and  M shipping lines. The ports are numbered  1 to  N. Each line is occupied by a Weitian. Each Weitian has an identification number.

The  i-th  (1iM) line connects port  Ai and  Bi  (AiBi) bidirectionally, and occupied by  Ci Weitian (At most one line between two ports).

When Mr.Quin only uses lines that are occupied by the same Weitian, the cost is  1 XiangXiangJi. Whenever Mr.Quin changes to a line that is occupied by a different Weitian from the current line, Mr.Quin is charged an additional cost of  1 XiangXiangJi. In a case where Mr.Quin changed from some Weitian  A's line to another Weitian's line changes to Weitian  A's line again, the additional cost is incurred again.

Mr.Quin is now at port  1 and wants to travel to port  N where live many fishes. Find the minimum required XiangXiangJi (If Mr.Quin can’t travel to port  N, print  1instead)
 

 

Input
There might be multiple test cases, no more than  20. You need to read till the end of input.

For each test case,In the first line, two integers  N  (2N100000) and  M  (0M200000), representing the number of ports and shipping lines in the city.

In the following m lines, each contain three integers, the first and second representing two ends  Ai and  Bi of a shipping line  (1Ai,BiN) and the third representing the identification number  Ci  (1Ci1000000) of Weitian who occupies this shipping line.
 

 

Output
For each test case output the minimum required cost. If Mr.Quin can’t travel to port  N, output  1 instead.
 

 

Sample Input
3 3 1 2 1 1 3 2 2 3 1 2 0 3 2 1 2 1 2 3 2
 

 

Sample Output
1 -1 2
 

解析 这题标程有些错误 而且是原题 既然标程是错的 也就不用按照 题解来写了 感觉现在最靠谱的思路就是 建虚点了 边权相同且相邻的点 建立一个虚点x

其他点到x距离为1的单向边 x到其他点距离为0单向边 把原来的去掉 跑最短路就是答案。这道题真是服了。。。

  1 #include <bits/stdc++.h>
  2 #define Pii pair<int,int>
  3 using namespace std;
  4 typedef long long ll;
  5 const int maxn=1e5+5;
  6 const int maxm=2e5+5;
  7 const int maxnn=1e6+5;
  8 const int inf=2147483647;
  9 vector<int> GG[maxn];
 10 int from[maxm],to[maxm],c[maxm];
 11 int n,cnt,nowc,dis[maxnn];             //cnt:n+虚点数
 12 bool v[maxm],vis[maxnn];
 13 struct node{
 14     int d,x;
 15     bool operator < (const node& b) const
 16     {return d>b.d;}
 17 };
 18 priority_queue<node> Q;
 19 int _first[maxnn],_tip[maxnn],_w[maxnn],_next[maxnn],edge;
 20 inline void dijk()
 21 {
 22     int i,u,vv,len,num;
 23     node tmp;
 24     for(i=1;i<=cnt;i++) dis[i]=inf;
 25     dis[1]=0;
 26     Q.push((node){0,1});
 27     while(!Q.empty())
 28     {
 29         tmp=Q.top();
 30         Q.pop();
 31         u=tmp.x;
 32         if(vis[u]==true) continue;
 33         vis[u]=true;
 34         num=_first[u];
 35         while(num!=-1)
 36         {
 37             vv=_tip[num];
 38             if(dis[u]!=inf&&dis[vv]>dis[u]+_w[num])
 39             {
 40                 dis[vv]=dis[u]+_w[num];
 41                 Q.push((node){dis[vv],vv});
 42             }
 43             num=_next[num];
 44         }
 45     }
 46     return;
 47 }
 48 inline void dfs(int x)
 49 {
 50     //add(x,cnt,1);
 51     _tip[++edge]=cnt;
 52     _w[edge]=1;
 53     _next[edge]=_first[x];
 54     _first[x]=edge;
 55 
 56     //add(cnt,x,0);
 57     _tip[++edge]=x;
 58     _w[edge]=0;
 59     _next[edge]=_first[cnt];
 60     _first[cnt]=edge;
 61 
 62     int i,len=GG[x].size(),num;
 63     for(i=0;i<len;i++)
 64     {
 65         num=GG[x][i];
 66         if(c[num]==nowc&&!v[num])
 67         {
 68             v[num]=true;
 69             if(from[num]==x) dfs(to[num]);
 70             else dfs(from[num]);
 71         }
 72     }
 73     return;
 74 }
 75 int main()
 76 {
 77     int i,m;
 78     while(scanf("%d%d",&n,&m)==2)
 79     {
 80         edge=0;
 81         cnt=n;
 82         memset(v,0,sizeof(v));
 83         memset(vis,0,sizeof(vis));
 84         memset(_first,-1,sizeof(_first));
 85         for(i=1;i<=m;i++)
 86         {
 87             scanf("%d%d%d",&from[i],&to[i],&c[i]);
 88             GG[from[i]].push_back(i);
 89             GG[to[i]].push_back(i);
 90         }
 91         for(i=1;i<=m;i++)
 92             if(!v[i])
 93             {
 94                 cnt++;
 95                 nowc=c[i];
 96                 dfs(from[i]);
 97             }
 98         dijk();
 99         if(dis[n]==inf) printf("-1\n");
100         else printf("%d\n",dis[n]);
101         //test();
102         for(i=1;i<=n;i++) GG[i].clear();
103     }
104     return 0;
105 }
View Code

转自  https://blog.csdn.net/jerry99s/article/details/81664117

 

转载于:https://www.cnblogs.com/stranger-/p/9476083.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值