一个“行走的结题报告”出的题目
来源:互联网 发布:excel数据自动更新 编辑:程序博客网 时间:2024/05/17 03:33
第一题:一到简单题
题目描述
Bessie正在计划一年一度的奶牛大集会,来自全国各地的奶牛将来参加这一次集会。当然,她会选择最方便的地点来举办这次集会。每个奶牛居住在 N(1<=N<=100,000) 个农场中的一个,这些农场由N-1条道路连接,并且从任意一个农场都能够到达另外一个农场。道路i连接农场A_i和B_i(1 <= A_i <=N; 1 <= B_i <= N),长度为L_i(1 <= L_i <= 1,000)。集会可以在N个农场中的任意一个举行。另外,每个牛棚中居住着C_i(0 <= C_i <= 1,000)只奶牛。在选择集会的地点的时候,Bessie希望最大化方便的程度(也就是最小化不方便程度)。比如选择第X个农场作为集会地点,它的不方便程度是其它牛棚中每只奶牛去参加集会所走的路程之和,(比如,农场i到达农场X的距离是20,那么总路程就是C_i*20)。帮助Bessie找出最方便的地点来举行大集会。
输入
第一行:一个整数N
第二到N+1行:第i+1行有一个整数C_i
第N+2行到2*N行,第i+N+1行为3个整数:A_i,B_i和L_i。
输出
一个数字表示答案
样例
Input Output
5
1
1
0
0
2
1 3 1
2 3 2
3 4 3
4 5 3 15
Output
15
时间 :
1s
数据范围
20%数据n<20
50%数据 n<2000
100%数据n<100,000
具体代码
#include<iostream>#include<cstdio>#include<cmath>#define N 100005#define LL long longusing namespace std;int n,num[N],tot[N],head[N];struct ii{ int to,next,w; ii (int to=0,int next=0,int w=0):to(to),next(next),w(w){}}Edge[N*2];LL f[N],ans=1e12;bool bo1[N],bo2[N];int dfs1(int x,int distant){ int q=head[x]; if(q==0)return num[x]; while(q){ int tov=Edge[q].to; if(!bo1[tov]){ distant+=Edge[q].w; f[1]+=(distant)*num[tov]; bo1[tov]=true; dfs1(tov,distant); tot[x]+=tot[tov]; distant-=Edge[q].w; } q=Edge[q].next; }}void dfs2(int x){ int q=head[x]; if(q==0)return; while(q){ int tov=Edge[q].to; if(!bo2[tov]){ int len=Edge[q].w; f[tov]=f[x]+tot[1]*len-tot[tov]*len*2; bo2[tov]=true; dfs2(tov); } q=Edge[q].next; }}int main(){ freopen("A.in","r",stdin); freopen("A.out","w",stdout); scanf("%d",&n); for(int i=1;i<=n;i++){ scanf("%d",&num[i]); tot[i]=num[i]; } for(int i=1;i<=n-1;i++){ int x,y,z; scanf("%d%d%d",&x,&y,&z); Edge[i*2-1]=ii(x,head[y],z); head[y]=i*2-1; Edge[i*2]=ii(y,head[x],z); head[x]=i*2; } bo1[1]=true; bo2[1]=true; dfs1(1,0); dfs2(1); for(int i=1;i<=n;i++) ans=min(ans,f[i]); cout<<ans<<endl; return 0;}
第二题:一道更简单的题
时间
1s
描述
有n个数围成一圈,每次操作后每个数变成和他距离在d以内的数字之和,求k次操作后每个数字模1000000007分别是多少
输入
第一行三个数n, d, k (1 ≤ n ≤ 1000, 0 ≤ d < n / 2 , 1 ≤ k ≤ 100 000 000),
第二行有n个正数,每个的大小都在int范围内
输出
一行n个数,空格隔开,表示结果。
样例
Input Ouput
5 1 1
1 2 10 3 6
9 13 15 19 10
Ouput
9 13 15 19 10
数据范围
10%数据满足n*k<10^6
30%数据满足 n<=100
50%数据满足 n<=500
100%数据满足n<=1000
解题思路
这道题真真666
先看代码
My 代码
#include<iostream>#include<cstdio>#include<cstring>#define N 1005#define M 1000000007#define LL long longusing namespace std;int n,d,k;struct ii{ int ju[N]; ii(){memset(ju,0,sizeof(ju));}};ii operator *(const ii a,const ii b){ ii c; for(int i=0;i<n;i++) for(int j=0;j<n;j++){ long long x=(((long long)a.ju[j]*b.ju[(i>=j)?(i-j):(n+i-j)])%M+c.ju[i])%M; c.ju[i]=x; } return c;}ii init;ii Pow(ii a,int b){ if(b==1)return a; ii temp=Pow(a,b/2); if(b&1)return a*(temp*temp); else return temp*temp;}ii tmp;int main(){ freopen("B.in","r",stdin); freopen("B.out","w",stdout); cin>>n>>d>>k; for(int i=0;i<n;i++) scanf("%d",&init.ju[i]); for(int i=0;i<d;i++) tmp.ju[i]=tmp.ju[n-i-1]=1; tmp.ju[d]=1; ii ans; ans=Pow(tmp,k); ans=init*ans; for(int i=0;i<n;i++)printf("%d ",ans.ju[i]); return 0;}
标程
#include <iostream>#include <iomanip>#include <fstream>#include <stdlib.h>#include <time.h>#include<cstring>#include<cstdio>#include<vector>#include<string>#include<algorithm>#include <limits.h>#include<cmath>#include<map>#include<queue>#include<set>using namespace std;long long n,d,k;long long m=1000000007;void mul(long long a[],long long b[]){ int i,j; long long c[1501]; for(i=0;i<n;++i)for(c[i]=j=0;j<n;++j)c[i]+=a[j]*b[i>=j?(i-j):(n+i-j)]%m; for(i=0;i<n;b[i]=c[i++]%m);}long long init[1501],tmp[1501];int main(){ freopen("B.in","r",stdin); freopen("B.out","w",stdout); long long i,j; scanf("%lld%lld%lld",&n,&d,&k); //k=1;d=1; for(i=0;i<n;++i)scanf("%lld",&init[i]); for(tmp[0]=i=1;i<=d;++i)tmp[i]=tmp[n-i]=1; while(k) { if(k&1)mul(tmp,init); mul(tmp,tmp); k>>=1; } for(i=0;i<n;++i)if(i)printf(" %lld",init[i]);else printf("%lld",init[i]); printf("\n"); return 0;}
有一点区别,不过核心都是一样的,“行走的结题报告”6666666
我的程序是用的快速幂矩阵乘法
如样例
init:1 2 10 3 6
tmp: 1 1 0 0 1
1 1 1 0 0
0 1 1 1 0
0 0 1 1 1
求第一个树相当于init*tmp
1表示在d范围内的附近,0表示不在
但是矩阵快速幂是O(n^3*logn)肯定要超时
所以把tmp:1 1 0 0 1 O(n^2*logn)
两个程序最重要的核心是:
for(i=0;i<n;++i)for(c[i]=j=0;j<n;++j)c[i]+=a[j]*b[i>=j?(i-j):(n+i-j)]%m;
本来应该是init * tmp*****tmp(k次)
由于矩阵乘法的结合律所以改写成init*(tmp*****tmp)
比如
a b
1 1
1 1
0 0
0 0
1 1
当i=0求第一个位置,
a[0]*b[0]
a[1]*b[4]
a[2]*b[3]
a[3]*b[2]
a[4]*b[1]
他是一个环,a是顺着的,b是反着的
同理当i=1时
a[0]*b[1]
a[1]*b[0]
a[2]*b[4]
a[3]*b[3]
a[4]*b[2]
总结:行走的结题报告真的666666666
第三题:最简单的题
时间
1s
题目描述
给出正整数n和k,计算j(n, k)=k mod 1 + k mod 2 + k mod 3 + … + k mod n的值,其中k mod i表示k除以i的余数。
例如j(5, 3)=3 mod 1 + 3 mod 2 + 3 mod 3 + 3 mod 4 + 3 mod 5=0+1+0+3+3=7
输入
第一行2个数n,k。
输出
一个数 j(n,k)。
样例
Input Output
5 3 7
Output
7
数据范围
50% 数据 满足 n<1e6
100%数据 满足 n<1e12 k<=n
解题思路:
比如n=36,k=36
36/?=
1~4 5 6 7 8 9 10~12 13~18 ……
0 7 6 5 5 4 3 2 ……
同理把36%?=
写出来会发现以上面那个分成几个区间,区间中的余数为等差数列
当i>k时,余数都为k
所以sum=n*k,然后再用区间分段减去等差数列的和
核心代码
for(LL i=1;i<=n;i=r+1){ j=m/i,l=m/(j+1)+1,r=m/j; if(r>n)r=n; sum-=(LL)(l+r)*j*(r-l+1)/2; }
具体代码
#include<iostream>#include<cstdio>#define LL long longusing namespace std;LL n,m,sum;int main(){ freopen("C.in","r",stdin); freopen("C.out","w",stdout); cin>>n>>m; sum=n*m; if(n>=m)n=m; LL j,l,r; for(LL i=1;i<=n;i=r+1){ j=m/i,l=m/(j+1)+1,r=m/j; if(r>n)r=n; sum-=(LL)(l+r)*j*(r-l+1)/2; } cout<<sum<<endl; return 0;}
行走的结题报告66666666666666!
- 一个“行走的结题报告”出的题目
- 写一个传智播客在学C#时出的题目
- 空间人物行走的向量实现(pku1835解题报告)
- 我出的面试题目
- 自己出的JavaScript题目
- 缓慢行走的青春
- 行走的机器人
- 行走的困疲
- 五月的行走
- 古镇的行走
- 角色的自动行走
- [math-intellect]据说是Einstein出的题目
- 我出的招网站程序员题目
- 一个简单的题目
- 一个栈的题目
- ------一个有意思的题目-----------
- sizeof的一个题目
- 一个有趣的题目
- 寄存器间接寻址方式
- js入门案例
- 出发
- CSS3d动画 animation 属性
- java.lang.NoSuchFieldError: No static field xxx of type I in class Lcom/XX/R$id; or its superclasses
- 一个“行走的结题报告”出的题目
- DBGridEh设置表中表
- CSDN文章转载方法
- JAVA----泛型方法
- CSS 入门(20160813-0013)
- LeetCode #2: Add Two Numbers
- Android上下文菜单和上下文操作
- 1-100求和数据结构
- java.lang.Long.toBinaryString()方法实例