Week 14

加一 

给定一个整数 n。你需要对它做 m次操作。在一次操作中,你要将这个数的每一位 d 替换成 d+1。比如,1912 在进行一次操作后将变成 21023。

请求出整数 n进行了 m 次操作后的长度。答案可能很大,输出对 10^9+7 取模后的结果。

输入格式

​ 第一行一个整数 t,表示测试单元的个数。

​ 接下来 t 行,每行有两个整数 n 和 m,表示最初的数字和进行多少次操作。

输出格式

​ 对于每个测试单元输出最终数字的长度,答案对 10^9+7取模。

样例输入

5
1912 1
5 6
999 1
88 2
12 100

样例输出

5
2
6
4
2115

数据规模

​ 所有数据保证 1≤t≤2⋅10^5,1≤n≤10^9,1≤m≤2⋅10^5。

对与每一个输入的数字列如 1 9 9 8,如果我们是直接去一个一个算的化,要进行操作数多起来就会很麻烦,那我们反过来向,8进行一个操作变成9,9进行一次操作变成1和0;

我们用一个数组来记录数字的变化,再用一个数组来记录数位; 

或者说,我们直接用一个二维数组来记录

a[i][j]表示这个数字进行了i次后,j这个数字的个数

159 进行一次操作

a[1][1]=a[0][2];a[1][5]=a[0][6];a[1][9]=a[0][1]+a[0][0];

1进行一次操作变成2,6进行一次操作变成6,9进行一次操作变成1和0;

我们就能对它进行dp;找到它的关系表达式 :

当j不等于9的时候a[i][j]=a[i-1][j+1]

当j等于9的时候 a[i][9]=(a[i-1][0]+a[i-1][1])%1e9+7;

因为这个数据的大小2*10^5*10够小,我们就能对数据进行预处理

2*10^5个数据,每个数据都是0-9;最多十次;

总共大小最大为2*10^6

#include <bits/stdc++.h>
using namespace std;
const int mod=1e9+7;
const int n=200005;
long long f[n][10];//a[i][j]表示进行i次操作后,j这个数字变成了几位数 
int main()
{
	int t;
	scanf("%d",&t);
	for(int i=0;i<10;i++) f[0][i]=1;//没有进行操作,有这个数字的化就是初始的1
	for(int i=1;i<=n;i++){//m最大为2e5,可以全部遍历一遍储存答案 
		for(int j=1;j<=9;j++){
			f[i][j-1]=f[i-1][j];
		}
		f[i][9]=(f[i-1][1]+f[i-1][0])%mod;
	} 
	while(t--){
		char s[20];
		int m,ans=0;
		scanf("%s %d",&s,&m);
		int cd=strlen(s);
		for(int i=0;i<cd;i++){
			int sz=s[i]-'0';
			ans+=f[m][sz];
			ans%=mod;
		}
		printf("%ld\n",ans);
	}
	return 0;
}
//例如0 1 2 3 4 5 6 7 8 9 9进行两次操作 
//第一次操作f[1][0]=f[0][1] f[1][1]=f[0][2]...
//f[1][9]=f[0][1]+f[0][0];    

跳跳

平面上给定了一些整点(横纵坐标均为整数的点),被称为 “魔法阵”。魔法少女派派想要在各魔法阵之间传送,每一次传送,她将使用下面的方式:

  1. 刚开始,派派已经位于某传送阵之上;
  2. 如果派派掌握一种魔法 (A,B),其中 A,B 均为整数。使用一次这个魔法可以让派派从任意整点 (X,Y) 瞬间移动至 (X+A,Y+B);
  3. 选择一种魔法并开始传送,在一次传送过程中可以使用多次该魔法,但在抵达下一个传送阵之前仅能使用这一种魔法

问派派至少需要掌握多少种魔法,才能在从任意魔法阵直接传送到任意魔法阵?

输入格式

第一行一个整数 N。

接下来一行 N 行,每行包含两个整数 Xi,Yi, 表示每个魔法阵的坐标。

输出格式

一个数,表示答案。

样例1输入

3
1 1
4 5
1 4

样例1输出

6

解释: 任务是从 (1,1) 传送至 (4,5) 以及 (1,4)、从 (4,5) 传送至 (1,1)以及 (1,4)、从 (1,4) 传送至 (1,1) 以及 (4,5) 。

注意你不能使用 (0,3)+(3,1)的魔法从 (1,1) 到达 (4,5)。因为每次移动,你只能使用一种魔法。

当然,你可以学习 (0,1),那样的话,从 (1,1) 到达 (1,4) 则需要使用 3 次(0,1) 魔法了。

样例2输入

3
1 1
2 2
1000000000 1000000000

样例2输出

2

数据规模

  • N∈[10,500]
  • Xi,Yi∈[0,10^9], 但保证坐标之间两两不同

这题看着emmm也不难,我们对于两个点,只需要算他们的距离,用最小的步子去走就行,步子可以小,可以多走一点,到达的点就更多,我的意思是:你可以慢慢来,一步一步地走,只要坚持走下去,能到达的地方会比那些大步流星匆匆走过的人多很多

对于每个点,我们都能进行遍历循环,就是对于第一个点,我们把它到第n个点的步子都记录下来,找到它到每个点的最小步伐,如果这个魔法没用过,我们就把答案++;

再对第二个点到各个点的魔法进行判断;

#include <bits/stdc++.h>//学map 
using namespace std;
pair<int,int> dui;
int main(){
	int n;
	int x,y;
	cin>>n;
	vector<pair<int,int> > v;//建立一个pair容器 
	for(int i=0;i<n;i++){
		cin>>x>>y;//输入点的坐标 
		v.push_back({x,y});
	}
	int ans=0;
	map<pair<int,int>, int> ditu;
	for(int i=0;i<n;i++){//从这个点到各个点的距离 
		for(int j=0;j<n;j++){
			if(j==i) continue;//再同一点不需要魔法 
			int dx=v[i].first-v[j].first;//两个点的x坐标差 
			int dy=v[i].second-v[j].second;//找到两个数的最大公约数
			if(dx==0&&dy!=0){//分析特殊的(0,y)(x,0)类型 
				dy/=fabs(dy);
			}
			else if(dx!=0&&dy==0){
				dx/=fabs(dx);
			}
			else{
				int gys=fabs(__gcd(dx,dy));
				dx/=gys;
				dy/=gys;//把他们都除以公约数得到最小的步伐
			}
			if(ditu[{dx,dy}]==0){//这个魔法没有用过 
				ditu[{dx,dy}]=1;
				ans++;
			}
		}
	}//这边已经几下所有的魔法了,下面进行去重 
	cout<<ans<<endl;
	return 0;
}

这边介绍一下stl里面的map

map是一个键值对,和python里面的字典是一个类型的

map<类型(键),类型(值)> 变量名

map可以直接通过它的键来访问值

或者通过迭代器来访问 

map<类型,类型> ::iteror it;

it->first访问第一个值,it->second访问第二个值

map.size()获得map的大小

map.find(key)找到key这个键对应的迭代器

map.erase(it)删除it这个迭代器

map.erase(first,last) 删除[first,last)这个区间里面的元素

map.begin() .end()获取开头和结尾

对于两个元神构成的键我们可以用pair<int,int> 

并用map[{a,b}]来找去对应的值

可以用insert来创建一个pair类型的map

map.insert(pair<int,int> int);

连续因子

这个题目,我们先找到他的因子,再看因子后面的数是不是也是它的因子,是的话继续,直到出现不是它因子的数,然后把它的长度记录下来,和最大值进行比较,并且把这个串因子的起点也记录下来然后输出就行

#include <bits/stdc++.h>
#define int long long
using namespace std;
signed main(){
    int n;
    cin>>n;
    int count=0;
    int digit=0;
    for(int i=2;i<=sqrt(n);i++){
        int sum=1;
        int nowcount=0;
        int digitnow=i;//记录这个在进行连续的数字 
        for(int j=i;n%j==0&&n%(sum*j)==0;j++){
            sum*=j;
            nowcount++;//记录数字连续个数
        }
        if(nowcount>count){
            count=nowcount;
            digit=digitnow;
        }
    }
    
    if(count==0){
        cout<<1<<endl;
        cout<<n<<endl;
    }
    else{
        cout<<count<<endl;
        for(int i=digit;i<digit+count;i++){
            if(i==digit+count-1) cout<<i<<endl;
            else{
                cout<<i<<'*';
            }
        }
    }
    return 0;
}

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值