华东交通大学2018年ACM“双基”程序设计竞赛部分题解
链接:https://ac.nowcoder.com/acm/contest/221/C
来源:牛客网
空间限制:C/C++ 32768K,其他语言65536K
64bit IO Format: %lld
题目描述
令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
-->
备注:
项数极大,朴素算法无法在规定时间内得出结果 解题思路:很明显的矩阵快速幂,比赛时没推出来。推出来了就是一个矩阵快速幂的板子题。
推倒方法可以参照: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
来源:牛客网
空间限制:C/C++ 32768K,其他语言65536K
64bit IO Format: %lld
题目描述
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
-->
数位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
来源:牛客网
空间限制:C/C++ 32768K,其他语言65536K
64bit IO Format: %lld
题目描述
最近,华东交通大学ACM训练基地的老阿姨被一个数学问题困扰了很久,她希望你能够帮她解决这个问题。
这个数学问题是这样的,给你一个N,要求你计算
输入描述:
多组输入,每行一个整数n(1<=n<=10^14)。
输出描述:
每行一个整数,表示答案。由于答案会很大你要对1000000007取模。
输入例子:
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
来源:牛客网
空间限制:C/C++ 32768K,其他语言65536K
64bit IO Format: %lld
题目描述
输入描述:
多组输入,每个样例第一行输入两个整数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
-->
思路: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“双基”程序设计竞赛部分题解的更多相关文章
- 华东交通大学2018年ACM“双基”程序设计竞赛 C. 公式题 (2) (矩阵快速幂)
题目链接:公式题 (2) 比赛链接:华东交通大学2018年ACM"双基"程序设计竞赛 题目描述 令f(n)=2f(n-1)+3f(n-2)+n,f(1)=1,f(2)=2 令g(n ...
- 华东交通大学2018年ACM“双基”程序设计竞赛 K
MIKU酱是个玩游戏氪金的人,游戏公司给她制定了新的规则,如果想从关卡i到关卡j,你需要交一些钱就可以了,但同时,MIKU酱的爸爸zjw很爱她,所以她可以每过一关就向她爸要一次钱,但她爸每次给他的钱是 ...
- 华东交通大学2018年ACM“双基”程序设计竞赛 D
摸鱼之王MIKU酱想去埃及玩,需要一个人陪同.小新和小磊都想陪MIKU酱一起去,但名额只有一个.所以小磊和小新决定用一个小游戏来决定谁和MIKU酱出去玩. 游戏的道具是21张塔罗牌,塔罗牌分 ...
- 华东交通大学2016年ACM“双基”程序设计竞赛 1007
Problem Description ACM小学妹在今天的暑假训练结束后,想看球赛放松一下.当他打开电脑时查询到联盟今天直播N场球赛,每场球赛的起止时间(S1,E1),(S2,E2),...,(SN ...
- 华东交通大学2016年ACM“双基”程序设计竞赛 1001
Problem Description 输入一个非负的int型整数,是奇数的话输出"ECJTU",是偶数则输出"ACM". Input 多组数据,每组数据输入一 ...
- 华东交通大学2016年ACM“双基”程序设计竞赛 1008
Problem Description halfyarn找你写个简单的题?好哒!给你n个整数,现在要求你选择两个位置的数,例如选择第pos_a个数a,和第pos_b个数b,给定ans=min(a,b) ...
- 华东交通大学2016年ACM“双基”程序设计竞赛 1005
Problem Description 最近侯ry感觉自己在数学方面的造诣不忍直视:他发现他的学习速率呈一个指数函数递增,疯狂的陷入学习的泥潭,无法自拔:他的队友发现了他的学习速率y=e^(b*lna ...
- 华东交通大学2016年ACM“双基”程序设计竞赛 1004
Problem Description LB是个十分喜欢钻研的人,对什么事都要搞明白.有一天他看到一个公式,((a-b)*c+d*e)/f=k.他想如果给定K的值,一共有多少种不同整数的组合(a,b, ...
- 华东交通大学2016年ACM“双基”程序设计竞赛 1010
Problem Description LB是个十分喜欢钻研的人,对什么事都要搞明白.有一天他学习到了阶乘,他十分喜欢,所以他在想一个问题.如果给定一个数n,求n!能不能被2016整除.LB算了好久都 ...
随机推荐
- CentOS7安装Jenkins,使用war方式直接运行或用yum方式安装运行
jenkins最简单的安装方式呢,就是直接去官网下载jenkins的war包,把war丢到tomcat里运行,直接就能打开了. Jenkins官网:https://jenkins.io/downloa ...
- MySQL 单个表锁死 对查询语句无响应
这个时候应该怀疑读取都被加锁,应该尝试使用 show processlist 查看每一个正在运行的进程. 可以看到这样一个列表,里面有使用者即用户,正在使用数据库的 host, 使用的 db 目前的 ...
- MySQL中KEY、PRIMARY KEY、UNIQUE KEY、INDEX 的区别
参考:MySQL中KEY.PRIMARY KEY.UNIQUE KEY.INDEX 的区别 对于题目中提出的问题,可以拆分来一步步解决.在 MySQL 中 KEY 和 INDEX 是同义.那这个问题就 ...
- 老男孩python学习自修第十七天【装饰器】
装饰器:在某个方法执行前后去执行其他新定义的行为 例如: #!/usr/bin/env python # _*_ coding:UTF-8 _*_ def before_say_hello(): pr ...
- django celery redis 定时任务
0.目的 在开发项目中,经常有一些操作时间比较长(生产环境中超过了nginx的timeout时间),或者是间隔一段时间就要执行的任务. 在这种情况下,使用celery就是一个很好的选择. cele ...
- [转]Java 的强引用、弱引用、软引用、虚引用
1.强引用(StrongReference) 强引用是使用最普遍的引用.如果一个对象具有强引用,那垃圾回收器绝不会回收它.如下: Object o=new Object(); // 强引用 当内存空间 ...
- 在文件保存中 os.getcwd() os.listdir() os.makedirs() os.mkdir() xx.join() ... 等函数 的使用介绍
path = 'C:\\Users\\zhangjunming\\Desktop\\PycharmProjects\\my_mgm' 1.xx.join(obj) 以xx为分隔符 对obj中的元素 ...
- LODOP设置判断后执行哪个
LODOP的语句是普通的语句,可以通过JS判断确定要执行哪个,或通过循环循环执行一些语句.如果需要执行某些打印项在哪些条件下不打印,不需要通过代码删除打印项,类似LODOP.SET_PRINT_STY ...
- Ibatis中的<trim>标签应用
<trim>的主要属性如下显示: <trim prefix="" prefixOverrides="" suffix="" ...
- hibernate一对多映射文件的配置
其中一个Customer对应多个LinkMan Customer的映射文件 Customer.hbm.xml-------------->一对多 <?xml version="1 ...