20200315t模拟赛 解题报告

题目在此

题目名称 幸运数 TOF函数 最短折叠
存盘文件名 lucky.cpp tof.cpp cuttle.cpp
输入文件名 lucky.in tof.in cuttle.in
输出文件名 lucky.out tof.out cuttle.out
时限 1s 1s 1s
内存限制 128M 128M 128M
【注意事项】: 请独立完成题目。

T1 幸运数

题目描述
如果一个数能被31整除且又包含31,我们称之为幸运数,请找出给定范围内所有的幸运数。
输入格式:
共一行,包含1个正整数n(0 <= n < 109)
输出格式:
[1,n]范围内幸运数的个数。
样例输入1:

400

样例输出1:

2

样例输入2:

4000

样例输出2:

7

法一(正解):

既然是大范围内的计数问题,那么它大概是用数位dp来做。

  • 如何描述状态?

  • f数组的第一维肯定存放当前位
    因为幸运数需要数位上有连续的 31 ,这个限制条件和第i位上放的数直接相关。于是我们用第二维描述第i位上存放j所得到的方案总数。
    幸运数还需要能被31整除,所以第三维存当前数除以31的余数
    综上

int f[N][N][N]; //第i位上放j,总共余数为k得到的方案总数
  • 如何转移?
LL dfs(int now,int sta,int md,bool lit);
//now表示当前位
//sta表示当前位上的数
//md表示放上当前位之后所得到的%31余数,从高位往低位放数
//lit表示是否一直达到上限
//返回值为当前状态下的方案总数

对于能被31整除的条件
a%n=(a%n+n)%n
(a+b)%n=(a+b%n)%n
(a+b)%n=(a%n+b)%n

显然余数为md的状态由(md*10+i)得来

对于数位中出现31的条件
极难正常的转移
若硬要做,我们需要把状态分门别类的存放。
已经有31的,还没出现31的,首位是1的。
那我们换一种方式考虑
能被31整除的数中
不是有31的,就是没31的。
那我们先做没有31的,用能被31整除的数的总数减去它,就是幸运数的个数了。
如何保证不出现31呢?
跟“”不要62“”的方法类似,碰到当前位是3,下一位是1的,不转移即可。
于是

LL res=0;
int maxn=(lit) ? dim[now-1] : 9;
for(int i=0;i<=maxn;i++) {
	if(sta==3&&i==1) continue;
	res+=dfs(now-1,i,(md*10+i)%MOD,(lit&&i==maxn));
} 
  • 边界条件?
  • 0位上只能放0,再判断能否整除即可。
if(now==0) return (sta==0&&md==0) ? 1 : 0;

Code:

#include<cstdio>
#include<cstring>
#include<iostream>
#define LL long long
using namespace std;
const int N=64;
const int MOD=31; 
int dim[N];
int f[N][N][N]; //第i位上放j,总共余数为k得到的方案总数
LL dfs(int now,int sta,int md,bool lit)
{
	if(now==0) return (sta==0&&md==0) ? 1 : 0; //---??
	if(!lit&&f[now][sta][md]!=-1) 
		return f[now][sta][md];
	LL res=0;
	int maxn=(lit) ? dim[now-1] : 9;
	for(int i=0;i<=maxn;i++) {
		if(sta==3&&i==1) continue;
		res+=dfs(now-1,i,(md*10+i)%MOD,(lit&&i==maxn));
	} 
	if(!lit) f[now][sta][md]=res;
	return res;
} 
LL prefix(LL x)
{
	memset(dim,0,sizeof dim);
	LL ans=x/31;
	int top=0;
	while(x>0) {
		dim[++top]=x%10;
		x=x/10;
	}
	for(int i=0;i<=dim[top];i++) 	
		ans-=dfs(top,i,i,i==dim[top]);
	ans++;
	return ans;
}
int main()
{
	freopen("lucky.in","r",stdin);
	freopen("lucky.out","w",stdout);
	LL a;
	cin>>a;
	memset(f,-1,sizeof f);
	cout<<prefix(a);
	return 0;
}

法二(分块打表):

没法一次暴力出0~1e9的幸运数总数,那我们每隔1e6
记录一次幸运数总数,对于输入的n,从最近的一个1e6开始暴力,这样最多只要算1e6次,是可以接受的。
这是用于打表的Code:

#include<cstdio>
#include<iostream>
#define LL long long
using namespace std;
int n;
const int N=1e9+5;
const int M=1e7;
int pm[M];
int tot=0;
bool check(int x)
{
	int top=0;
	int tmp=0;
	int flag=0;
	while(x>0) {
		tmp=x%10;
		x=x/10;
		if(tmp==1) 
			flag=1;
		else if(tmp==3) {
			if(flag==1) return true;
			else flag=0;
		}
		else flag=0;
	}
	return false;
}
void prime()
{
	int i,j;
	for(i=31;i<=n;i+=31) {
		if(check(i))
			pm[++tot]=i;//printf("%d,",i);
	}
	return;
}
int main()
{
//	freopen("lucky.in","r",stdin);
	freopen("lucky.cpp","w",stdout);
	cout<<"int pm[]={";
	n=1e9;
  //  cin>>n;
	prime();
//	cout<<tot;
	for(int i=0;i<=1e9;i+=1e6) {
		cout<<(lower_bound(pm+1,pm+tot+1,i)-pm-1)<<",";
	}
	cout<<"};";
	return 0;
}

注意表的大小要控制在1000左右。
这是提交的程序:

#include<iostream>
#include<cstdio>
using namespace std;
const int N=1e5;
int n,m;
int tot=0;
int pm[N]={0,1595,3190,4783,9476,11070,12663,14257,15851,17444,19038,20632,22224,23817,28508,30101,31695,33290,34882,36475,38071,39664,41258,42852,47544,49136,50731,52324,53916,55511,57103,58695,90954,92549,97239,98833,100427,102020,103614,105208,106801,108395,109989,111581,116272,117866,119459,121053,122648,124240,125833,127429,129022,130616,135306,136900,138492,140087,141680,143272,144867,146459,148051,149646,154339,155932,157526,159120,160713,162307,163901,165494,167088,168682,173373,174966,176560,178153,179747,181342,182934,184527,186123,187716,192407,194001,195595,197187,198782,200375,201967,203562,205154,206746,211438,213033,214626,216220,217814,219407,221001,222595,224188,225782,230473,232065,233658,235252,236845,238439,240034,241626,243219,244815,249507,251101,252695,254289,255881,257476,259069,260661,262256,263848,268537,270132,271727,273320,274914,276508,278101,279695,311953,313546,318238,319832,321424,323017,324611,326204,327798,329393,330985,332578,337273,338866,340460,342054,343648,345240,346835,348428,350020,351615,356304,357896,359491,361086,362679,364273,365867,367460,369054,370648,375338,376932,378526,380118,381711,383305,384898,386492,388087,389679,394370,395966,397559,399153,400747,402341,403933,405528,407121,408713,413406,414998,416590,418185,419780,421373,422967,424561,426154,427748,432440,434033,435627,437221,438813,440406,442000,443593,445187,446782,451471,453064,454660,456253,457847,459441,461035,462627,464222,465815,470506,472101,473693,475285,476880,478475,480068,481662,483256,484849,489540,491134,492727,494321,495915,497507,499100,500694,532952,534546,539239,540831,542424,544020,545613,547207,548801,550395,551987,553582,558272,559864,561459,563051,564643,566238,567833,569426,571020,572614,577306,578900,580494,582087,583681,585275,586867,588460,590054,591647,596339,597934,599526,601119,602715,604308,605902,607496,609090,610682,615375,616968,618560,620155,621747,623339,624934,626529,628122,629716,634408,636001,637595,639189,640782,642376,643970,645562,647155,648749,653439,655033,656628,658220,659813,661409,663002,664596,666190,667784,672474,674069,675662,677254,678849,680441,682033,714292,746550,778808,811066,843324,875582,907840,940098,972356,1004614,1006208,1007800,1009393,1014084,1015677,1017271,1018866,1020458,1022051,1023647,1025240,1057498,1059092,1063784,1065376,1066971,1068564,1070156,1071751,1073343,1074935,1076530,1078125,1082815,1084409,1086003,1087596,1089190,1090784,1092377,1093971,1095565,1097157,1101848,1103442,1105035,1106629,1108224,1109816,1111409,1113005,1114598,1116192,1120882,1122476,1124068,1125663,1127256,1128848,1130443,1132035,1133627,1135222,1139915,1141508,1143102,1144696,1146289,1147883,1149477,1151070,1152664,1154258,1158949,1160542,1162136,1163729,1165323,1166918,1168510,1170103,1171699,1173292,1177983,1179577,1181171,1182763,1184358,1185951,1187543,1189138,1190730,1192322,1197014,1198609,1200202,1201796,1203390,1204983,1206577,1208171,1209764,1211358,1216049,1217641,1219234,1220828,1222421,1224015,1225610,1227202,1228795,1230391,1235083,1236677,1238271,1239865,1241457,1243052,1244645,1246237,1278495,1280087,1284776,1286371,1287966,1289559,1291153,1292747,1294340,1295934,1297528,1299121,1303813,1305407,1306999,1308592,1310186,1311779,1313373,1314968,1316560,1318153,1322848,1324441,1326035,1327629,1329223,1330815,1332410,1334003,1335595,1337190,1341879,1343471,1345066,1346661,1348254,1349848,1351442,1353035,1354629,1356223,1360913,1362507,1364101,1365693,1367286,1368880,1370473,1372067,1373662,1375254,1379945,1381541,1383134,1384728,1386322,1387916,1389508,1391103,1392696,1394288,1398981,1400573,1402165,1403760,1405355,1406948,1408542,1410136,1411729,1413323,1418015,1419608,1421202,1422796,1424388,1425981,1427575,1429168,1430762,1432357,1437046,1438639,1440235,1441828,1443422,1445016,1446610,1448202,1449797,1451390,1456081,1457676,1459268,1460860,1462455,1464050,1465643,1467237,1499495,1501088,1505779,1507373,1508966,1510560,1512154,1513746,1515339,1516933,1518526,1520120,1524813,1526405,1527998,1529594,1531187,1532781,1534375,1535969,1537561,1539156,1543846,1545438,1547033,1548625,1550217,1551812,1553407,1555000,1556594,1558188,1562880,1564474,1566068,1567661,1569255,1570849,1572441,1574034,1575628,1577221,1581913,1583508,1585100,1586693,1588289,1589882,1591476,1593070,1594664,1596256,1600949,1602542,1604134,1605729,1607321,1608913,1610508,1612103,1613696,1615290,1619982,1621575,1623169,1624763,1626356,1627950,1629544,1631136,1632729,1634323,1639013,1640607,1642202,1643794,1645387,1646983,1648576,1650170,1651764,1653358,1658048,1659643,1661236,1662828,1664423,1666015,1667607,1669202,1670797,1672390,1677083,1678677,1680270,1681864,1683458,1685051,1686645,1688239,1720497,1722090,1726781,1728374,1729968,1731563,1733155,1734748,1736344,1737937,1739531,1741125,1745817,1747409,1749004,1750597,1752189,1753784,1755376,1756968,1758563,1760158,1764848,1766442,1768036,1769629,1771223,1772817,1774410,1776004,1777598,1779190,1783881,1785475,1787068,1788662,1790257,1791849,1793442,1795038,1796631,1798225,1802915,1804509,1806101,1807696,1809289,1810881,1812476,1814068,1815660,1817255,1821948,1823541,1825135,1826729,1828322,1829916,1831510,1833103,1834697,1836291,1840982,1842575,1844169,1845762,1847356,1848951,1850543,1852136,1853732,1855325,1860016,1861610,1863204,1864796,1866391,1867984,1869576,1871171,1872763,1874355,1879047,1880642,1882235,1883829,1885423,1887016,1888610,1890204,1891797,1893391,1898082,1899674,1901267,1902861,1904454,1906048,1907643,1909235,1941493,1943089,1947781,1949375,1950969,1952563,1954155,1955750,1957343,1958935,1960530,1962122,1966811,1968406,1970001,1971594,1973188,1974782,1976375,1977969,1979563,1981156,1985848,1987442,1989034,1990627,1992221,1993814,1995408,1997003,1998595,2000188,2004883,2006476,2008070,2009664,2011258,2012850,2014445,2016038,2017630,2019225,2023914,2025506,2027101,2028696,2030289,2031883,2033477,2035070,2036664,2038258,2042948,2044542,2046136,2047728,2049321,2050915,2052508,2054102,2055697,2057289,2061980,2063576,2065169,2066763,2068357,2069951,2071543,2073138,2074731,2076323,2081016,2082608,2084200,2085795,2087390,2088983,2090577,2092171,2093764,2095358,2100050,2101643,2103237,2104831,2106423,2108016,2109610,2111203,2112797,2114392,2119081,2120674,2122270,2123863,2125457,2127051,2128645,2130237,2162495,2164088,2168779,2170374,2171966,2173558,2175153,2176748,2178341,2179935,2181529,2183122,2187813,2189407,2191000,2192594,2194188,2195780,2197373,2198967,2200560,2202154,2206847,2208439,2210032,2211628,2213221,2214815,2216409,2218003,2219595,2221190,2225880,2227472,2229067,2230659,2232251,2233846,2235441,2237034,2238628,2240222,2244914,2246508,2248102,2249695,2251289,2252883,2254475,2256068,2257662,2259255,2263947,2265542,2267134,2268727,2270323,2271916,2273510,2275104,2276698,2278290,2282983,2284576,2286168,2287763,2289355,2290947,2292542,2294137,2295730,2297324,2302016,2303609,2305203,2306797,2308390,2309984,2311578,2313170,2314763,2316357,2321047,2322641,2324236,2325828,2327421,2329017,2330610,2332204,2333798,2335392,2340082,2341677,2343270,2344862,2346457,2348049,2349641,2351236,2383494,2385087,2389780,2391374,2392967,2394561,2396155,2397748,2399342,2400936,2402528,2404121,2408812,2410405,2411999,2413594,2415186,2416779,2418375,2419968,2421562,2423156,2427848,2429440,2431035,2432628,2434220,2435815,2437407,2438999,2440594,2442189,2446879,2448473,2450067,2451660,2453254,2454848,2456441,2458035,2459629,2461221,2465912,2467506,2469099,2470693,2472288,2473880,2475473,2477069,2478662,2480256,2484946,2486540,2488132,2489727,2491320,2492912,2494507,2496099,2497691,2499286,2503979,2505572,2507166,2508760,2510353,2511947,2513541,};
bool check(int x)
{
	int top=0;
	int tmp=0;
	int flag=0;
	while(x>0) {
		tmp=x%10;
		x=x/10;
		if(tmp==1) 
			flag=1;
		else if(tmp==3) {
			if(flag==1) return true;
			else flag=0;
		}
		else flag=0;
	}
	return false;
}
void prime()
{
	int i,j;
	for(i=m;i<=n;i+=31) {
		if(check(i))
			tot++;
	}
	return;
}
int main()
{
	freopen("lucky.in","r",stdin);
	freopen("lucky.out","w",stdout);
	cin>>n;
	tot+=pm[(n/1000000)];
	m=(n/1000000)*1000000;
	while(m%31!=0) m++;
	prime();
	cout<<tot;
	return 0;
}

T2 TOF函数

题目描述
一个十进制数正整数x表示为 T   n   , T   n 1   , T   n 2   . . . T   2   T   1   T~n~,T~n-1~,T~n-2~ ... T~2~T~1~ (Tn代表x的最高位的值,以此类推,T1代表 x x 的最低位的值),定义 x x 的TOF函数的值为:
T O F ( x ) TOF(x) =Tn * 2n-1 + Tn-1 * 2n-2 + … + T2 * 21 + T1 * 20.
现在给你两个数E,P(0 <= E,P < 109),请计算[0,P]范围内有多少个数的TOF函数的值**<=TOF(E)**。
输入:
第1行为两个个正整数两个正整数代表E,P
输出:
一个整数代表对应结果
样例输入:

5 100

样例输出:

13

思路

  • 如何描述状态?
  • 跟上一题一样,第一维描述位数,第二维描述该位数上所填的数,
  • 那如何保证所有状态的tof都小于等于tof(E)呢?
  • 因为 n < = 1 0 9 n<=10^9 .所以 t o f n < 20000 tof(n)<20000 ,显然可以开第三位的空间来描述。
    综上
int f[N][N][20000]; //第i位上放j,该位和其后的位组成的数tof小于等于k的个数 
  • 如何转移?
  • 第i位上放j小于等于Max的数,那么第i-1位上无论放什么都要 < = M a x 2 i 1 <=Max-2^i-1 ,于是得出状转方程
	LL res=0;
	int maxn=(lit) ? dim[now-1] : 9;
	int sufMax=Max-pow2[now-1]*sta;
	for(int i=0;i<=maxn;i++) 
		res+=dfs(now-1,i,sufMax,(i==maxn&&lit));
  • 边界条件?
  • 第0位上只能放0,所以tof=0,如果要求的 M a x > = 0 Max>=0 ,则是一种方案,否则不行。
if(now==0) return (sta==0&&Max>=0) ? 1 : 0;

Code:

#include<cstdio>
#include<cstring>
#include<iostream>
#define LL long long
using namespace std;
const int N=12;
int dim[N];
int f[N][N][20000]; //第i位上放j,tof小于等于k的个数 
const int pow2[]={1,2,4,8,16,32,64,128,256,512,1024,2048,4096,8192,16384,32768};
int all;
LL dfs(int now,int sta,int Max,bool lit)
{
	if(now==0) return (sta==0&&Max>=0) ? 1 : 0;
	if(!lit&&f[now][sta][Max]!=-1) 
		return f[now][sta][Max];
	LL res=0;
	int maxn=(lit) ? dim[now-1] : 9;
	int sufMax=Max-pow2[now-1]*sta;
	for(int i=0;i<=maxn;i++) 
		res+=dfs(now-1,i,sufMax,(i==maxn&&lit));
	if(!lit) f[now][sta][Max]=res;
	return res;
} 
LL prefix(LL x)
{
	memset(dim,0,sizeof dim);
	int top=0;
	while(x>0) {
		dim[++top]=x%10;
		x=x/10;
	}
	LL res=0;
	for(int i=0;i<=dim[top];i++) 
		res+=dfs(top,i,all,i==dim[top]);
	return res;
}
inline int tof(int x)
{
	int res=0;
	int i,j;
	i=0;
	while(x>0) {
		res+=pow2[i]*(x%10);
		i++;
		x/=10;
	}	
	return res;
}
int main()
{
	freopen("tof.in","r",stdin);
	freopen("tof.out","w",stdout);
	int E,P;
	cin>>E>>P;
	memset(f,-1,sizeof f);
	all=tof(E);
	cout<<prefix(P);
	return 0;
}
发布了17 篇原创文章 · 获赞 3 · 访问量 1697

猜你喜欢

转载自blog.csdn.net/qq_45646484/article/details/104937320