链接:https://ac.nowcoder.com/acm/contest/221/C
来源:牛客网

C-公式题(2)
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 32768K,其他语言65536K
64bit IO Format: %lld

题目描述

令f(n)=2*f(n-1)+3*f(n-2)+n,f(1)=1,f(2)=2
令g(n)=g(n-1)+f(n)+n*n,g(1)=2
告诉你n,输出g(n)的结果,结果对1e9+7取模

输入描述:

多组输入,每行一个整数n(1<=n<=1e9),如果输入为0,停止程序。

输出描述:

在一行中输出对应g(n)的值,结果对1e9+7取模。

输入例子:
1
5
9
456
0
输出例子:
2
193
11956
634021561

-->

示例1

输入

复制

1
5
9
456
0

输出

复制

2
193
11956
634021561

说明

多组输入,输入为0时,终止程序

备注:

项数极大,朴素算法无法在规定时间内得出结果

解题思路:很明显的矩阵快速幂,比赛时没推出来。推出来了就是一个矩阵快速幂的板子题。
推倒方法可以参照:https://www.jianshu.com/p/25eba927d9da
推倒过程:
g(n)=g(n-1)+f(n)+n*n;
g(n)=g(n-1)+2*f(n-1)+3*f(n-2)+n*n+n;
g(n)=g(n-1)+2*f(n-1)+3*f(n-2)+(n-1)^2+3*(n-1)+2;

得到矩阵:

再通过简单的递推一下,左边n代3,可以得到一个常数矩阵,再乘以右边矩阵的n-2次方,得到矩阵的第一行第一列元素即为答案。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <queue>
using namespace std;
const int mod=1e9+;
const int maxn=;
typedef long long ll;
ll n;
struct Matrix{
ll a[maxn][maxn];
}; Matrix mul(Matrix a,Matrix b) //两矩阵相乘
{
Matrix temp;
memset(temp.a,,sizeof(temp.a));
for(int i=;i<maxn;i++)
for(int j=;j<maxn;j++)
for(int k=;k<maxn;k++)
temp.a[i][j]=(temp.a[i][j]+a.a[i][k]*b.a[k][j])%mod;
return temp;
} Matrix qpow(Matrix a,ll n) //矩阵快速幂
{
Matrix ans;
memset(ans.a,,sizeof(ans.a));
for(int i=;i<maxn;i++)
ans.a[i][i]=; //化成单位矩阵
while(n)
{
if(n&) ans=mul(ans,a);
a=mul(a,a);
n/=;
}
return ans;
} int main()
{
Matrix A,C;
A.a[][]=,A.a[][]=,A.a[][]=,A.a[][]=,A.a[][]=,A.a[][]=;
A.a[][]=,A.a[][]=,A.a[][]=,A.a[][]=,A.a[][]=,A.a[][]=;
A.a[][]=,A.a[][]=,A.a[][]=,A.a[][]=,A.a[][]=,A.a[][]=;
A.a[][]=,A.a[][]=,A.a[][]=,A.a[][]=,A.a[][]=,A.a[][]=;
A.a[][]=,A.a[][]=,A.a[][]=,A.a[][]=,A.a[][]=,A.a[][]=;
A.a[][]=,A.a[][]=,A.a[][]=,A.a[][]=,A.a[][]=,A.a[][]=; C.a[][]=,C.a[][]=,C.a[][]=,C.a[][]=,C.a[][]=,C.a[][]=;
while(cin>>n)
{
if(n==) break;
if(n==)
{
cout<<<<endl;
continue;
}
cout<<mul(C,qpow(A,n-)).a[][]<<endl;
}
return ;
}

链接:https://ac.nowcoder.com/acm/contest/221/G
来源:牛客网

G-7的意志
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 32768K,其他语言65536K
64bit IO Format: %lld

题目描述

定义一个序列a:7,77,777......,7777777(数字全为7的正整数,且长度可以无限大)
clearlove7需要从含有7的意志的数里获得力量,如果一个整数能被序列a中的任意一个数字整除,并且其数位之和为序列a中任意一个数字的倍数,那么这个数字就含有7的意志,现在给你一个范围[n,m],问这个范围里有多少个数字含有7的意志。

输入描述:

多组输入,每行两个个整数n,m(1<=n<=m<=1e18),如果输入为"0 0",停止程序。

输出描述:

每一行输出含有7的意志的数的个数。

输入例子:
1 7
1 100
1 1000
0 0
输出例子:
1
3
21

-->

示例1

输入

复制

1 7
1 100
1 1000
0 0

输出

复制

1
3
21

说明

1到100中符合条件的数字为7,70,77
数位dp,不会可以参考博客:https://blog.csdn.net/brazy/article/details/77427699
定义一个三维dp,分别存储到枚举的当前位置,模7的余数,数位和模7的余数。
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<string>
#include<vector>
#include<stack>
#include<bitset>
#include<cstdlib>
#include<cmath>
#include<set>
#include<list>
#include<deque>
#include<map>
#include<queue>
using namespace std;
typedef long long ll;
const double PI = acos(-1.0);
const double eps = 1e-;
const int INF = 0x3f3f3f3f;
const ll mod=1e9+;
ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
ll n,m,a[];
ll dp[][][];
ll dfs(ll pos,ll pre,ll sum,bool limit)
{
if(pos==-)
return (pre%==&&sum%==); //枚举到了最后一位并且合法
if(!limit&&dp[pos][pre][sum]!=-)
return dp[pos][pre][sum];
ll up=limit?a[pos]:;
ll ans=;
for(int i=;i<=up;i++)
ans+=dfs(pos-,(pre*+i)%,(sum+i)%,limit&&i==a[pos]);
if(!limit) //记忆化
dp[pos][pre][sum]=ans;
return ans;
}
ll solve(ll x)
{
ll pos=;
while(x) //对数进行数位拆分
{
a[pos++]=x%;
x/=;
}
return dfs(pos-,,,true); //从最高位开始枚举
}
int main()
{
ios_base::sync_with_stdio(false); cin.tie();
memset(dp, -, sizeof(dp));
while(cin>>n>>m)
{
if(n==&&m==) break;
cout<<solve(m)-solve(n-)<<endl;
}
return ;
}

链接:https://ac.nowcoder.com/acm/contest/221/I
来源:牛客网

I-数学题
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 32768K,其他语言65536K
64bit IO Format: %lld

题目描述

题面描述
最近,华东交通大学ACM训练基地的老阿姨被一个数学问题困扰了很久,她希望你能够帮她解决这个问题。
这个数学问题是这样的,给你一个N,要求你计算

gcd(a,b)表示a和b的最大公约数

输入描述:

多组输入,每行一个整数n(1<=n<=10^14)。

输出描述:

每行一个整数,表示答案。由于答案会很大你要对1000000007取模。

输入例子:
4
10
输出例子:
6
35

-->

示例1

输入

复制

4
10

输出

复制

6
35

说明

样例一,2+4=6。
样例二,2+4+5+6+8+10=35。 思路:欧拉公式的延伸:对于一个数,与其互质的数的总和是euler(n)*n/2。
所以结果就是n*(n+1)/2-euler(n)*n/2. 注意取模不能直接除2,需要乘2对1e9+7的逆元。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod=1e9+;
ll n,m; ll euler(ll n)
{
ll ans=n;
ll i;
for(i=;i<=sqrt(n);i++)
{
if(n%i==)
{
ans=ans/i*(i-);
while(n%i==)
n/=i;
}
}
if(n>)
ans=ans/n*(n-);
return ans;
}
ll pow_mod(ll a, ll b)
{
ll ret = ;
ll p=mod;
while(b)
{
if(b & )
ret = (ret * a) % p;
a = (a * a) % p;
b >>= ;
}
return ret;
}
int main()
{
while(cin>>n)
{
if(n==)
{
cout<<<<endl;
continue;
}
ll inv=pow_mod(,mod-);
cout<<((n%mod)*((n+-euler(n))%mod)%mod)*inv%mod<<endl;
}
return ;
}

链接:https://ac.nowcoder.com/acm/contest/221/K
来源:牛客网

MIKU酱的氪金宝典
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 32768K,其他语言65536K
64bit IO Format: %lld

题目描述

MIKU酱是个玩游戏氪金的人,游戏公司给她制定了新的规则,如果想从关卡i到关卡j,你需要交一些钱就可以了,但同时,MIKU酱的爸爸zjw很爱她,所以她可以每过一关就向她爸要一次钱,但她爸每次给他的钱是固定的,MIKU酱是个不会节省的女孩,哪怕每次多出来的钱,她也会拿去买肥宅快乐水,所以每次要的钱一定花完,因为MIKU酱不想挨骂,所以希望每次他爸给她的钱最少。
tips(到达第n关即通过,每到达一关一定能通过这关)

输入描述:

多组输入,每个样例第一行输入两个整数n,m(2<=n<=200,1<=m<=1000)表示关卡和规则的数量,接下来m行规则,每行输入x,y,w(w<=1000),表示从关卡x到y需要缴纳w的费用,保证题目有解,不会出现x=y的情况

输出描述:

输出一行,代表最少的钱

输入例子:
4 4
1 2 2
1 3 1
2 4 3
3 4 1
输出例子:
1

-->

示例1

输入

复制

4 4
1 2 2
1 3 1
2 4 3
3 4 1

输出

复制

1
思路:n的范围不大,三层循环就可以过,但是比赛时没想到,比赛用的dfs,但是超时,经过剪枝了下,还是过了,题解用的dijkstra
dfs是记录两个东西,一个当前位置,一个该条路的边权最大值,走到节点n时,ans保留dfs出的最小值。
dijkstra做法直接把松弛操作改改就可以了 dfs做法:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod=1e9+;
const ll inf=0x3f3f3f3f;
ll n,m;
typedef pair<int,int> P;
vector<P> mp[];
int vis[],ans;
void dfs(int x,int cost) //x为当前位置,cost为该条路的边权最大值
{
if(x==n)
{
ans=min(ans,cost);
return;
}
if(cost>=ans) //剪枝,如果还未到n就已经比现在最优结果大直接返回,去掉会超时
return;
int ss=mp[x].size();
for(int i=;i<ss;i++)
{
if(vis[mp[x][i].first]==)
{
vis[mp[x][i].first]=;
dfs(mp[x][i].first,max(cost,mp[x][i].second));
vis[mp[x][i].first]=;
}
}
}
int main()
{
while(cin>>n>>m)
{
ios_base::sync_with_stdio(false); cin.tie();
for(int i=;i<=n;i++) mp[i].clear();
ans=inf;
memset(vis,,sizeof(vis));
for(int i=;i<=m;i++)
{
int u,v,w;
cin>>u>>v>>w;
P q;
q.first=v;
q.second=w;
mp[u].push_back(q);
}
vis[]=;
dfs(,);
cout<<ans<<endl;
}
return ;
}

dijkstra做法:

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<string>
#include<vector>
#include<stack>
#include<bitset>
#include<cstdlib>
#include<cmath>
#include<set>
#include<list>
#include<deque>
#include<map>
#include<queue>
using namespace std;
typedef long long ll;
const double PI = acos(-1.0);
const double eps = 1e-;
const int INF = 0x3f3f3f3f;
const ll mod=1e9+;
int n,m,dis[],vis[];
struct qnode{
int v,d;
qnode(int a,int b):v(a),d(b){}
bool operator<(const qnode& a)const{
return d>a.d;
}
};
struct edge{
int v,w;
edge(int a,int b):v(a),w(b){}
};
vector<edge> mp[];
priority_queue<qnode> pq;
void dij()
{
memset(vis,,sizeof(vis));
memset(dis,INF,sizeof(dis));
dis[]=;
pq.push(qnode(,));
while(!pq.empty())
{
qnode x=pq.top();
pq.pop();
int u=x.v;
for(int i=;i<mp[u].size();i++)
{
int v=mp[u][i].v;
int w=mp[u][i].w;
int tmp=dis[u];
tmp=max(dis[u],w);
if(dis[v]>tmp) //如果该条路边权最大值小于当前最优值,则更新
{
dis[v]=tmp;
pq.push(qnode(v,dis[v]));
}
}
}
} int main()
{
ios_base::sync_with_stdio(false); cin.tie();
while(cin>>n>>m)
{
for(int i=;i<=n;i++) mp[i].clear();
for(int i=;i<m;i++)
{
int u,v,w;
cin>>u>>v>>w;
mp[u].push_back(edge(v,w));
}
dij();
cout<<dis[n]<<endl;
}
return ;
}

华东交通大学2018年ACM“双基”程序设计竞赛部分题解的更多相关文章

  1. 华东交通大学2018年ACM“双基”程序设计竞赛 C. 公式题 (2) (矩阵快速幂)

    题目链接:公式题 (2) 比赛链接:华东交通大学2018年ACM"双基"程序设计竞赛 题目描述 令f(n)=2f(n-1)+3f(n-2)+n,f(1)=1,f(2)=2 令g(n ...

  2. 华东交通大学2018年ACM“双基”程序设计竞赛 K

    MIKU酱是个玩游戏氪金的人,游戏公司给她制定了新的规则,如果想从关卡i到关卡j,你需要交一些钱就可以了,但同时,MIKU酱的爸爸zjw很爱她,所以她可以每过一关就向她爸要一次钱,但她爸每次给他的钱是 ...

  3. 华东交通大学2018年ACM“双基”程序设计竞赛 D

      摸鱼之王MIKU酱想去埃及玩,需要一个人陪同.小新和小磊都想陪MIKU酱一起去,但名额只有一个.所以小磊和小新决定用一个小游戏来决定谁和MIKU酱出去玩.    游戏的道具是21张塔罗牌,塔罗牌分 ...

  4. 华东交通大学2016年ACM“双基”程序设计竞赛 1007

    Problem Description ACM小学妹在今天的暑假训练结束后,想看球赛放松一下.当他打开电脑时查询到联盟今天直播N场球赛,每场球赛的起止时间(S1,E1),(S2,E2),...,(SN ...

  5. 华东交通大学2016年ACM“双基”程序设计竞赛 1001

    Problem Description 输入一个非负的int型整数,是奇数的话输出"ECJTU",是偶数则输出"ACM". Input 多组数据,每组数据输入一 ...

  6. 华东交通大学2016年ACM“双基”程序设计竞赛 1008

    Problem Description halfyarn找你写个简单的题?好哒!给你n个整数,现在要求你选择两个位置的数,例如选择第pos_a个数a,和第pos_b个数b,给定ans=min(a,b) ...

  7. 华东交通大学2016年ACM“双基”程序设计竞赛 1005

    Problem Description 最近侯ry感觉自己在数学方面的造诣不忍直视:他发现他的学习速率呈一个指数函数递增,疯狂的陷入学习的泥潭,无法自拔:他的队友发现了他的学习速率y=e^(b*lna ...

  8. 华东交通大学2016年ACM“双基”程序设计竞赛 1004

    Problem Description LB是个十分喜欢钻研的人,对什么事都要搞明白.有一天他看到一个公式,((a-b)*c+d*e)/f=k.他想如果给定K的值,一共有多少种不同整数的组合(a,b, ...

  9. 华东交通大学2016年ACM“双基”程序设计竞赛 1010

    Problem Description LB是个十分喜欢钻研的人,对什么事都要搞明白.有一天他学习到了阶乘,他十分喜欢,所以他在想一个问题.如果给定一个数n,求n!能不能被2016整除.LB算了好久都 ...

随机推荐

  1. js根据ip自动获取地址(省市区)

    HTML: <html> <head> <meta charset="utf-8"> <meta name="viewport& ...

  2. [转帖]Docker save and load镜像保存

    Docker save and load镜像保存 https://www.cnblogs.com/zhuochong/p/10064350.html docker save 和 load 以及 imp ...

  3. NOIP2015提高组复赛B 子串

    题目链接:https://ac.nowcoder.com/acm/contest/263/B 题目大意: 略 分析: 设preA(i)为字符串A中第1个字符到第i个字符构成的字符串. 设preB(i) ...

  4. github上测试服出现bug,如何回滚并获得合并之前的分支

    使用场景: 当我们提交了一个pr,但是该pr合并之后,经过在测试测试有问题,需要回滚.这个时候主master代码将会被回滚到提交你的pr之前的代码.而你的pr由于已经被合并过了,所以无法继续提交. 这 ...

  5. python数据结构与算法第六天【栈与队列】

    1.栈和队列的原理 栈:后进先出(LIFO),可以使用顺序表和链表实现 队列:先进先出(FIFO),可以使用顺序表和链表实现 2.栈的实现(使用顺序表实现) #!/usr/bin/env python ...

  6. git的简单使用(一些小操作,持续更新)

    第一次使用git的过程记录 参考了两个文章 菜鸟教程-git简明指南 阮一峰-常用git命令清单 git的几个工作区(此处参考了上面的两篇介绍) 简单步骤如下 git init 在当前目录建立工作区 ...

  7. 五、compose 部署 GitLab 应用

    1.我们部署的是sameersbn/docker-gitlab这个镜像. docker pull sameersbn/gitlab 2.配置文件,我们不需要去run它,只需要先下载一个compose的 ...

  8. github---无命令可视化界面操作

    最近工作需要,研究了一下git,这个东西挺实用,给我的感觉并不是那么简单使用,我认为还可以再深入的研究一下,挺好玩的~ 说一下我的学习路线: 1.先看的廖老师的博客:https://www.liaox ...

  9. Software License Manager

    slmgr -ilc lenovo.xrm-ms slmgr -ipk lenovo-lenovo-lenovo-lenovo-lenovo

  10. c++ string去除首尾 空格、\n、\r、\t

    string s = " test "; size_t n = s.find_last_not_of(" \r\n\t"); if (n != string:: ...